lib/mongo_mapper/plugins/keys.rb in mongo_mapper-0.7.5 vs lib/mongo_mapper/plugins/keys.rb in mongo_mapper-0.7.6
- old
+ new
@@ -1,8 +1,10 @@
module MongoMapper
module Plugins
module Keys
+ autoload :Key, 'mongo_mapper/plugins/keys/key'
+
def self.configure(model)
model.key :_id, ObjectId
end
module ClassMethods
@@ -15,32 +17,33 @@
def keys
@keys ||= HashWithIndifferentAccess.new
end
def key(*args)
- key = Key.new(*args)
- keys[key.name] = key
-
- create_accessors_for(key)
- create_key_in_descendants(*args)
- create_indexes_for(key)
- create_validations_for(key)
-
- key
+ Key.new(*args).tap do |key|
+ keys[key.name] = key
+ create_accessors_for(key)
+ create_key_in_descendants(*args)
+ create_indexes_for(key)
+ create_validations_for(key)
+ end
end
def key?(key)
keys.keys.include?(key.to_s)
end
def using_object_id?
object_id_key?(:_id)
end
+ def object_id_keys
+ keys.keys.select { |key| keys[key].type == ObjectId }.map(&:to_sym)
+ end
+
def object_id_key?(name)
- key = keys[name.to_s]
- key && key.type == ObjectId
+ object_id_keys.include?(name.to_sym)
end
def to_mongo(instance)
return nil if instance.nil?
instance.to_mongo
@@ -51,27 +54,30 @@
value.is_a?(self) ? value : load(value)
end
# load is overridden in identity map to ensure same objects are loaded
def load(attrs)
+ return nil if attrs.nil?
begin
klass = attrs['_type'].present? ? attrs['_type'].constantize : self
klass.new(attrs, true)
rescue NameError
new(attrs, true)
end
end
private
- def accessors_module
- module_defined = if method(:const_defined?).arity == 1 # Ruby 1.9 compat check
- const_defined?('MongoMapperKeys')
- else
- const_defined?('MongoMapperKeys', false)
- end
+ def key_accessors_module_defined?
+ if method(:const_defined?).arity == 1 # Ruby 1.9 compat check
+ const_defined?('MongoMapperKeys')
+ else
+ const_defined?('MongoMapperKeys', false)
+ end
+ end
- if module_defined
+ def accessors_module
+ if key_accessors_module_defined?
const_get 'MongoMapperKeys'
else
const_set 'MongoMapperKeys', Module.new
end
end
@@ -152,11 +158,11 @@
def initialize(attrs={}, from_database=false)
default_id_value(attrs)
if from_database
@new = false
- self.attributes = attrs
+ load_from_database(attrs)
else
@new = true
assign(attrs)
end
@@ -168,17 +174,15 @@
end
def attributes=(attrs)
return if attrs.blank?
- attrs.each_pair do |name, value|
- writer_method = "#{name}="
-
- if respond_to?(writer_method)
- self.send(writer_method, value)
+ attrs.each_pair do |key, value|
+ if respond_to?(:"#{key}=")
+ self.send(:"#{key}=", value)
else
- self[name.to_s] = value
+ self[key] = value
end
end
end
def attributes
@@ -253,10 +257,21 @@
def embedded_keys
keys.values.select { |key| key.embeddable? }
end
private
+ def load_from_database(attrs)
+ return if attrs.blank?
+ attrs.each do |key, value|
+ if respond_to?(:"#{key}=") && !self.class.key?(key)
+ self.send(:"#{key}=", value)
+ else
+ self[key] = value
+ end
+ end
+ end
+
def default_id_value(attrs)
unless attrs.nil?
provided_keys = attrs.keys.map { |k| k.to_s }
unless provided_keys.include?('_id') || provided_keys.include?('id')
write_key :_id, BSON::ObjectID.new
@@ -276,70 +291,31 @@
if key.embeddable? && value.is_a?(key.type)
value._parent_document = self
end
end
- def read_key(name)
- if key = keys[name]
- var_name = "@#{name}"
- value = key.get(instance_variable_get(var_name))
+ def read_key(key_name)
+ if key = keys[key_name]
+ value = key.get(instance_variable_get(:"@#{key_name}"))
set_parent_document(key, value)
- instance_variable_set(var_name, value)
+ instance_variable_set(:"@#{key_name}", value)
else
- raise KeyNotFound, "Could not find key: #{name.inspect}"
+ raise KeyNotFound, "Could not find key: #{key_name.inspect}"
end
end
def read_key_before_typecast(name)
- instance_variable_get("@#{name}_before_typecast")
+ instance_variable_get(:"@#{name}_before_typecast")
end
def write_key(name, value)
- key = keys[name]
-
+ key = keys[name.to_s]
set_parent_document(key, value)
- instance_variable_set "@#{name}_before_typecast", value
- instance_variable_set "@#{name}", key.set(value)
+ instance_variable_set :"@#{name}_before_typecast", value
+ instance_variable_set :"@#{name}", key.set(value)
end
end
- class Key
- attr_accessor :name, :type, :options, :default_value
- def initialize(*args)
- options = args.extract_options!
- @name, @type = args.shift.to_s, args.shift
- self.options = (options || {}).symbolize_keys
- self.default_value = self.options.delete(:default)
- end
-
- def ==(other)
- @name == other.name && @type == other.type
- end
-
- def embeddable?
- type.respond_to?(:embeddable?) && type.embeddable? ? true : false
- end
-
- def number?
- [Integer, Float].include?(type)
- end
-
- def get(value)
- if value.nil? && !default_value.nil?
- if default_value.respond_to?(:call)
- return default_value.call
- else
- return default_value
- end
- end
-
- type.from_mongo(value)
- end
-
- def set(value)
- type.to_mongo(value)
- end
- end
end
end
end