lib/mongodoc/document.rb in mongodoc-0.1.2 vs lib/mongodoc/document.rb in mongodoc-0.2.0
- old
+ new
@@ -1,31 +1,47 @@
require 'mongodoc/bson'
require 'mongodoc/query'
require 'mongodoc/attributes'
require 'mongodoc/criteria'
+require 'mongodoc/finders'
+require 'mongodoc/named_scope'
module MongoDoc
class DocumentInvalidError < RuntimeError; end
class NotADocumentError < RuntimeError; end
- class Document
- extend MongoDoc::Attributes
- include Validatable
+ module Document
- attr_accessor :_id
- alias :id :_id
- alias :to_param :_id
+ def self.included(klass)
+ klass.class_eval do
+ include Attributes
+ extend ClassMethods
+ extend Finders
+ extend NamedScope
+ include Validatable
+ alias :id :_id
+ alias :to_param :_id
+ end
+ end
+
def initialize(attrs = {})
self.attributes = attrs
end
def ==(other)
return false unless self.class === other
self.class._attributes.all? {|var| self.send(var) == other.send(var)}
end
+ def attributes
+ self.class._attributes.inject({}) do |hash, attr|
+ hash[attr] = send(attr)
+ hash
+ end
+ end
+
def attributes=(attrs)
attrs.each do |key, value|
send("#{key}=", value)
end
end
@@ -37,11 +53,11 @@
def save(validate = true)
return _root.save(validate) if _root
return _save(false) unless validate and not valid?
false
end
-
+
def save!
return _root.save! if _root
raise DocumentInvalidError unless valid?
_save(true)
end
@@ -54,22 +70,32 @@
end
end
end
def update_attributes(attrs)
+ strict = attrs.delete(:__strict__)
self.attributes = attrs
- return _propose_update_attributes(self, path_to_root(attrs), false) if valid?
- false
+ return false unless valid?
+ if strict
+ _strict_update_attributes(_path_to_root(self, attrs), false)
+ else
+ _naive_update_attributes(_path_to_root(self, attrs), false)
+ end
end
def update_attributes!(attrs)
+ strict = attrs.delete(:__strict__)
self.attributes = attrs
raise DocumentInvalidError unless valid?
- _propose_update_attributes(self, path_to_root(attrs), true)
+ if strict
+ _strict_update_attributes(_path_to_root(self, attrs), true)
+ else
+ _naive_update_attributes(_path_to_root(self, attrs), true)
+ end
end
- class << self
+ module ClassMethods
def bson_create(bson_hash, options = {})
new.tap do |obj|
bson_hash.each do |name, value|
obj.send("#{name}=", MongoDoc::BSON.decode(value, options))
end
@@ -82,57 +108,95 @@
def collection_name
self.to_s.tableize.gsub('/', '.')
end
- def count
- collection.count
- end
-
def create(attrs = {})
instance = new(attrs)
_create(instance, false) if instance.valid?
instance
end
-
+
def create!(attrs = {})
instance = new(attrs)
raise MongoDoc::DocumentInvalidError unless instance.valid?
_create(instance, true)
instance
end
- def criteria
- Criteria.new(self)
- end
+ protected
- def find_one(id)
- MongoDoc::BSON.decode(collection.find_one(id))
+ def _create(instance, safe)
+ instance.send(:notify_before_save_observers)
+ instance._id = collection.insert(instance, :safe => safe)
+ instance.send(:notify_save_success_observers)
+ instance._id
+ rescue Mongo::MongoDBError => e
+ instance.send(:notify_save_failed_observers)
+ raise e
end
end
protected
def _collection
self.class.collection
end
-
- def _propose_update_attributes(src, attrs, safe)
- return _parent.send(:_propose_update_attributes, src, attrs, safe) if _parent
- _update_attributes(attrs, safe)
+
+ def _naive_update_attributes(attrs, safe)
+ return _root.send(:_naive_update_attributes, attrs, safe) if _root
+ _collection.update({'_id' => self._id}, MongoDoc::Query.set_modifier(attrs), :safe => safe)
end
+ def _strict_update_attributes(attrs, safe, selector = {})
+ return _root.send(:_strict_update_attributes, attrs, safe, _selector_path_to_root('_id' => _id)) if _root
+ _collection.update({'_id' => _id}.merge(selector), MongoDoc::Query.set_modifier(attrs), :safe => safe)
+ end
+
def _save(safe)
+ notify_before_save_observers
self._id = _collection.save(self, :safe => safe)
+ notify_save_success_observers
+ self._id
+ rescue Mongo::MongoDBError => e
+ notify_save_failed_observers
+ raise e
end
- def _update_attributes(attrs, safe)
- _collection.update({'_id' => self._id}, MongoDoc::Query.set_modifier(attrs), :safe => safe)
+ def before_save_callback(root)
+ self._id = Mongo::ObjectID.new if new_record?
end
- class << self
- def _create(instance, safe)
- instance._id = collection.insert(instance, :safe => safe)
- end
+ def save_failed_callback(root)
+ self._id = nil
end
+
+ def save_success_callback(root)
+ root.unregister_save_observer(self)
+ end
+
+ def save_observers
+ @save_observers ||= []
+ end
+
+ def register_save_observer(child)
+ save_observers << child
+ end
+
+ def unregister_save_observer(child)
+ save_observers.delete(child)
+ end
+
+ def notify_before_save_observers
+ save_observers.each {|obs| obs.before_save_callback(self) }
+ end
+
+ def notify_save_success_observers
+ save_observers.each {|obs| obs.save_success_callback(self) }
+ end
+
+ def notify_save_failed_observers
+ save_observers.each {|obs| obs.save_failed_callback(self) }
+ end
+
end
end