Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add if_update option for conditionally updating counter in after_update hook. #15

Merged
merged 4 commits into from
Mar 16, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## v1.1.1

* Add :if_update option in order to allow counter to be conditionally increment/decrement counter when an update is made to a referenced/embedded object.

## v1.0.0

* Remove version dependency to work with rails 4. Breaks compatibility with ruby 1.9.2 and older
Expand Down
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,28 @@ end

comment_count will get incremented / decremented only when `:if` condition returns `true`

### Conditional Counter After Update

In conjunction with the conditional counter, if you want to maintain counter after an update to an object, then you can specify it using `:if_update`

Using same example as above, in the referrenced/Embedded document, add an additional condition for counter using `:if_update`

````rb
class Comment
include Mongoid::Document
include Mongoid::MagicCounterCache

belongs_to :post

field :remark
field :is_published, type: Boolean, default: false

counter_cache :post, :if => Proc.new { |act| (act.is_published) }, :if_update => Proc.new { |act| act.changes['is_published'] }
end
````

When a comment is saved, comment_count will get incremented / decremented if the is_published field is dirty.

## TODO

1. Add additional options parameters
Expand Down
2 changes: 1 addition & 1 deletion lib/mongoid/magic-counter-cache/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module Mongoid
module MagicCounterCache
VERSION = "1.1.0"
VERSION = "1.1.1"
end
end
22 changes: 22 additions & 0 deletions lib/mongoid/magic_counter_cache.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ def counter_cache(*args, &block)
name = options[:class] || args.first.to_s
counter_name = get_counter_name(options)
condition = options[:if]
update_condition = options[:if_update]

callback_proc = ->(doc, inc) do
result = condition_result(condition, doc)
Expand All @@ -86,8 +87,29 @@ def counter_cache(*args, &block)
end
end

update_callback_proc = ->(doc) do
return if condition.nil?
return if update_condition.nil? # Don't execute if there is no update condition.
return unless update_condition.call(doc) # Determine whether to execute update increment/decrements.

inc = condition.call(doc) ? 1 : -1

if doc.embedded?
parent = doc._parent
if parent.respond_to?(counter_name)
increment_association(parent, counter_name.to_sym, inc)
end
else
relation = doc.send(name)
if relation && relation.class.fields.keys.include?(counter_name)
increment_association(relation, counter_name.to_sym, inc)
end
end
end

after_create( ->(doc) { callback_proc.call(doc, 1) })
after_destroy(->(doc) { callback_proc.call(doc, -1) })
after_update( ->(doc) { update_callback_proc.call(doc) })

end

Expand Down
2 changes: 1 addition & 1 deletion lib/mongoid_magic_counter_cache/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module MongoidMagicCounterCache
VERSION = "1.1.0"
VERSION = "1.1.1"
end
2 changes: 2 additions & 0 deletions spec/models/article.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ class Article
include Mongoid::Document

embeds_many :reviews
embeds_many :update_reviews

field :title
field :review_count, type: Integer, default: 0
field :update_review_count, type: Integer, default: 0

end
2 changes: 2 additions & 0 deletions spec/models/post.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ class Post

has_many :comments

field :update_comment_count, :type => Integer, :default => 0
has_many :update_comments
end
11 changes: 11 additions & 0 deletions spec/models/update_comment.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class UpdateComment
include Mongoid::Document
include Mongoid::MagicCounterCache

belongs_to :post

field :remark
field :is_published, type: Boolean, default: false

counter_cache :post, :if => Proc.new { |act| (act.is_published) }, :if_update => Proc.new { |act| act.changes['is_published'] }
end
10 changes: 10 additions & 0 deletions spec/models/update_review.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class UpdateReview
include Mongoid::Document
include Mongoid::MagicCounterCache

embedded_in :article
counter_cache :article, :if => Proc.new { |act| (act.is_published) }, :if_update => Proc.new { |act| act.changes['is_published'] }

field :comment
field :is_published, type: Boolean, default: false
end
Loading