Skip to content

Commit

Permalink
Adding new feature to easily track all associations instead of specif…
Browse files Browse the repository at this point in the history
…ying them one-by-one. Bumping up version number to 1.1.0, too.
  • Loading branch information
caseydreier committed Jan 30, 2010
1 parent d634d57 commit 915aa87
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 5 deletions.
8 changes: 8 additions & 0 deletions 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.
21 changes: 19 additions & 2 deletions 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 <tt>:all</tt> 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?

Expand Down
15 changes: 15 additions & 0 deletions lib/dirty_associations/instance_methods.rb
Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion lib/dirty_associations/version.rb
@@ -1,3 +1,3 @@
module DirtyAssociations
VERSION = '1.0.0'.freeze
VERSION = '1.1.0'.freeze
end
23 changes: 23 additions & 0 deletions test/dirty_associations_test.rb
Expand Up @@ -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
18 changes: 16 additions & 2 deletions test/model_definitions.rb
Expand Up @@ -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
Expand All @@ -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
8 changes: 8 additions & 0 deletions test/schema.rb
Expand Up @@ -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
3 changes: 3 additions & 0 deletions test/test_helper.rb
Expand Up @@ -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)
Expand Down

0 comments on commit 915aa87

Please sign in to comment.