-
-
Save bowsersenior/721971 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%w(rubygems mongoid rspec).each do |gem| | |
require gem | |
end | |
Mongoid.configure do |config| | |
name = "dirty_track_test" | |
host = "localhost" | |
config.master = Mongo::Connection.new.db(name) | |
config.persist_in_safe_mode = false | |
end | |
RSpec.configure do |config| | |
config.before(:each) do | |
Mongoid.master.collections.reject { |c| c.name == 'system.indexes'}.each(&:drop) | |
end | |
end | |
class Person | |
include Mongoid::Document | |
field :name | |
embeds_one :address | |
embeds_many :phones | |
references_many :projects | |
# dirty tracking of embedded documents | |
attr_writer :embedded_changes, :referenced_changes | |
def referenced_changes | |
puts "SELF: #{(self.methods - Object.methods).sort.to_yaml}" | |
puts "CHILDREN: #{((self.associations)).inspect}" | |
@referenced_changes ||= begin | |
self.associations.keys.each do |assoc_name| | |
self.send(assoc_name).inject({}) do |memo, obj| | |
memo.merge(obj.each{|c| c.send(:changes) if c.send(:changed?)}) | |
end | |
end | |
end | |
end | |
def embedded_changes | |
@embedded_changes ||= begin | |
self._children.inject({}) do |memo, child| | |
memo.merge(child.changes) if child.changed? | |
end | |
end | |
end | |
def changes | |
original_value = super | |
if original_value.blank? | |
embedded_changes # need to merge these two hashes | |
referenced_changes # but make sure to detect nil values | |
else | |
original_value.merge(embedded_changes).merge(referenced_changes) | |
end | |
end | |
def changed? | |
super || self._children.any?(&:changed?) # what about changes to referenced docs? | |
end | |
end | |
class Address | |
include Mongoid::Document | |
field :city | |
embedded_in :person, :inverse_of => :address | |
end | |
class Phone | |
include Mongoid::Document | |
field :number, :type => Integer | |
embedded_in :person, :inverse_of => :phones | |
end | |
class Project | |
include Mongoid::Document | |
field :title | |
referenced_in :person, :inverse_of => :projects | |
end | |
describe Person do | |
context "parent document" do | |
it "should detect the changes" do | |
@person = Person.new(:name => "Sachin") | |
@person.save! | |
@person.name = "Sagar" | |
@person.changed.should be_true | |
end | |
end | |
context "parent document with embedded one document" do | |
it "should detect the changes of the embedded one address document when the address city is changed" do | |
@person = Person.new(:name => "Sachin") | |
@person.create_address(:city => "Kathmandu") | |
@person.changed?.should be_false | |
@person.address.city = "Lalitpur" | |
@person.changed?.should be_true | |
@person.changes["city"].should include("Lalitpur") | |
end | |
end | |
context "parent document with embedded many document" do | |
it "should detect the changes of the embedded many phones document when the phone number is changed" do | |
@person = Person.new(:name => "Sachin") | |
@person.phones.create!(:number => 980) | |
@person.phones.first.number.should == 980 | |
@person.changed?.should be_false | |
@person.phones.first.number = 400 | |
@person.changed?.should be_true | |
@person.changes["number"].should include(400) | |
end | |
end | |
context "parent document with references many documents" do | |
it "should detect the changes of the referenced many project document when the project title is changed" do | |
@person = Person.create!(:title => "Sachin") | |
@project = Project.new(:name => "Gliding") | |
@person.projects << @project | |
@person.changes | |
@person.changed?.should be_true | |
# @person.changes["title"].should include("Gliding") | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Yes, I know dirty_associations is for activerecord. If you look at the code for dirty_associations, you can get some ideas on how to do something similar for mongoid. But I think you'll see that it won't be easy! Also, dirty_associations doesn't record changes to an associated record, only the addition or removal of an associated record.