diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..f35344d --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,8 @@ +# Version 1.1.0 + +* Added the option to pass the :all option to the method, keep_track_of, in order to track all available associations + without having to specify each single one. + +# Version 1.0.0 + +* Initial release. \ No newline at end of file diff --git a/lib/dirty_associations/base.rb b/lib/dirty_associations/base.rb index 16aec1c..3b5eccc 100644 --- a/lib/dirty_associations/base.rb +++ b/lib/dirty_associations/base.rb @@ -1,8 +1,25 @@ module DirtyAssociations - module Base #:nodoc: + module Base - # This is the main class method to define which associations in the model one would like to make dirty. + # This is the main class method to define which associations in the model one would like to track changes. # This can be called before or after associations are defined. Validation occurs on object instantiation. + # You can also just pass the symbol :all which will automatically track all available associations. + # + # Example: + # + # class Task < ActiveRecord::Base + # has_many :comments + # belongs_to :user + # has_and_belongs_to_many :keywords + # + # keep_track_of :comments, :keywords + # end + # + # Or: + # class Task < ActiveRecord::Base + # #...same association definitions as above...# + # keep_track_of :all # => will track :comments, :keywords, and :user + # end def keep_track_of(*associations) raise ArgumentError, "Please specify at least one association to track" if associations.empty? diff --git a/lib/dirty_associations/instance_methods.rb b/lib/dirty_associations/instance_methods.rb index bfa4689..228d0f0 100644 --- a/lib/dirty_associations/instance_methods.rb +++ b/lib/dirty_associations/instance_methods.rb @@ -6,9 +6,19 @@ module InstanceMethods # any changes to the associations are tracked. After the block is executed, the associations are reset. def enable_dirty_associations(&block) raise ArgumentError, 'Must be called with a block!' unless block_given? + + # If the user passes ":all", scan the model and set tracking on all the associations + # That is unless there is an "all" assocition defined, in which case, continue without setting all assocations + populate_dirty_associtaions_with_all_associations! if !is_valid_association?(:all) && self.class.dirty_associations.delete(:all) + + # Go and validate to make sure these associations are named properly validate_dirty_associations + + # Initialize the initial values and construct the dirty methods for each association initialize_dirty_associations yield + + # Clear out when the block ends clear_association_changes end @@ -68,6 +78,11 @@ def validate_dirty_associations raise DirtyAssociations::InvalidAssociationError, "#{association_name} does not seem to be a valid association to track" unless is_valid_association?(association_name) end end + + # Collect all association names and populate the class variable +dirty_associations+ with them. + def populate_dirty_associtaions_with_all_associations! + self.class.dirty_associations = self.class.reflect_on_all_associations.map(&:name) + end end diff --git a/lib/dirty_associations/version.rb b/lib/dirty_associations/version.rb index 8179f0f..8cd0521 100644 --- a/lib/dirty_associations/version.rb +++ b/lib/dirty_associations/version.rb @@ -1,3 +1,3 @@ module DirtyAssociations - VERSION = '1.0.0'.freeze + VERSION = '1.1.0'.freeze end \ No newline at end of file diff --git a/test/dirty_associations_test.rb b/test/dirty_associations_test.rb index 358b056..3a7a5ed 100644 --- a/test/dirty_associations_test.rb +++ b/test/dirty_associations_test.rb @@ -412,4 +412,27 @@ class Keyword < ActiveRecord::Base end end + test "calling 'keep_track_of :all' should track all listed associations for a model" do + # The Comment model calls: keep_track_of :all + @comment1.enable_dirty_associations do + assert_equal ["task", "responses", "parent"].sort, @comment1.class.dirty_associations.map {|a| a.to_s}.sort + end + end + + test "association tracking returns valid objects for self-referencing associations" do + # The Comment model uses a self-referencing association for responses to a comment. + @comment1.enable_dirty_associations do + # Create a new child comment + new_comment = @comment1.responses.create(:body => 'Newest response', :task => @t1) + + # Make sure the associations changed properly + assert @comment1.associations_changed? + + # Assert that the added object is the same as the one created + assert_equal new_comment, @comment1.responses_added.first + end + end + + + end \ No newline at end of file diff --git a/test/model_definitions.rb b/test/model_definitions.rb index 93bab7c..989007a 100644 --- a/test/model_definitions.rb +++ b/test/model_definitions.rb @@ -6,7 +6,8 @@ class Task < ActiveRecord::Base :foreign_key => "task_id" has_many :blocking_tasks, :through => :dependencies - + has_many :comments + has_and_belongs_to_many :keywords belongs_to :user @@ -28,10 +29,23 @@ class Todo < ActiveRecord::Base class Keyword < ActiveRecord::Base has_and_belongs_to_many :tasks - end class Dependency < ActiveRecord::Base belongs_to :task, :foreign_key => "task_id" belongs_to :blocking_task, :class_name => "Task", :foreign_key => "blocking_task_id" end + +class Comment < ActiveRecord::Base + + keep_track_of :all # track all associations. # Note that this method call can be placed before association definitions. + + belongs_to :task + has_many :responses, + :class_name => "Comment", + :foreign_key => :parent_id + belongs_to :parent, + :class_name => "Comment", + :primary_key => :parent_id, + :foreign_key => :id +end diff --git a/test/schema.rb b/test/schema.rb index bb96b93..76779e6 100644 --- a/test/schema.rb +++ b/test/schema.rb @@ -33,4 +33,12 @@ t.integer "blocking_task_id", :precision => 38, :scale => 0, :null => false end + create_table "comments", :force => true do |t| + t.integer "parent_id", :precision => 38, :scale => 0, :null => true + t.integer "task_id", :precision => 38, :scale => 0, :null => false + t.text "body" + t.datetime "created_at" + t.datetime "updated_at" + end + end \ No newline at end of file diff --git a/test/test_helper.rb b/test/test_helper.rb index b61cbb8..8d8acd7 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -54,6 +54,9 @@ def load_test_data @t1.keywords << @k1 @t1.keywords << @k2 + @comment1 = @t1.comments.create(:body => 'Comment text') + @comment1_response = @comment1.responses.create(:body => "Comment response", :task => @t1) + @t1.todos.create(:description => "New Todo Item", :open => true) @task_with_preferred_user = Task.create(:name => "Blocked Test", :user => @u1, :preferred_user => @preferred_user)