module ObjectIdentifier class Deidentifier attr_accessor :str, :options def initialize(str, options = {}) @str = str.to_s @options = options end # Class method for reconstructing an object or set of objects from its/their # self-identifying string(s). # # @overload self.identify(str) # @param str [String] the String to deidentify # @overload self.identify(str, options) # @param str [String] the object to identify # @param [Hash] options the options for building a customized # self-identifier # @option options [String, nil] :klass object class name override # @option options [Fixnum] :limit maximum number of objects to display # from a collection # # @return [Object] the object represented by the identifier String def self.deidentify(obj, options = {}) new(obj, options).deidentify end # @return [Object] the object represented by the identifier String def deidentify if multiple_objects_to_deidentify? # deidentify_multiple_objects else deidentify_single_object(str) end end private def deidentify_multiple_objects end def deidentify_single_object(object_str) klass = determine_class(object_str) attributes = extract_attributes(object_str) case (model = klass.constantize) when ActiveRecord::Base model.where(select_core_attributes(attributes)).first else model.new(attributes) end end def multiple_objects_to_deidentify? str.starts_with?("[") && str.ends_with?("]") end def determine_class(object_str) options.fetch(:klass) { object_str[/\A(\w+)/, 1] } end def extract_attributes(object_str) result = object_str[/\[(.+)\]/, 1] return if result == "no objects" JSON.parse(jsonify_attributes_str(result)) end def jsonify_attributes_str(attributes_str) "{ #{attributes_str} }".gsub(/ (\w+):/, ' "\1":') end def select_core_attributes(attributes) attributes.select { |key, _| key.in?(klass.column_names) } end end end