From 606a41bb7adb73902520195ac10f6e5458bd77df Mon Sep 17 00:00:00 2001 From: Sameer Tilak Date: Thu, 27 Feb 2014 18:13:47 +0530 Subject: [PATCH] Added condition for counter Added 2 models for specs changed ruby version to 2.1.0 and mongoid version to 4.0.0 --- .travis.yml | 2 +- Gemfile | 1 + lib/mongoid/magic_counter_cache.rb | 60 +++++++++++++----- spec/models/comment.rb | 11 ++++ spec/models/post.rb | 9 +++ spec/mongoid/magic_counter_cache_spec.rb | 77 +++++++++++++++++++++++- 6 files changed, 142 insertions(+), 18 deletions(-) create mode 100644 spec/models/comment.rb create mode 100644 spec/models/post.rb diff --git a/.travis.yml b/.travis.yml index 11a115a..3172f10 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,3 @@ language: ruby rvm: - - 1.9.3 + - 2.1.0 diff --git a/Gemfile b/Gemfile index f5baf63..67b79c5 100644 --- a/Gemfile +++ b/Gemfile @@ -2,3 +2,4 @@ source "http://rubygems.org" # Specify your gem's dependencies in mongoid_magic_counter_cache.gemspec gemspec +gem 'mongoid', '4.0.0.alpha2' diff --git a/lib/mongoid/magic_counter_cache.rb b/lib/mongoid/magic_counter_cache.rb index 42dc281..1ef8093 100644 --- a/lib/mongoid/magic_counter_cache.rb +++ b/lib/mongoid/magic_counter_cache.rb @@ -46,32 +46,60 @@ module ClassMethods def counter_cache(*args, &block) options = args.extract_options! name = options[:class] || args.first.to_s - + if options[:field] counter_name = "#{options[:field].to_s}" else - counter_name = "#{model_name.demodulize.underscore}_count" + counter_name = "#{model_name.name.demodulize.underscore}_count" end + + condition = options[:if] + after_create do |doc| - if doc.embedded? - parent = doc._parent - parent.inc(counter_name.to_sym, 1) if parent.respond_to? counter_name - else - relation = doc.send(name) - if relation && relation.class.fields.keys.include?(counter_name) - relation.inc(counter_name.to_sym, 1) + result = condition.nil? ? true : condition.call(doc) + #condition.each do |key, value| + # if doc.fields.keys.include?(key) and doc[key.to_sym] == value + # else + # result = false + # break + # end + #end + #end + + if result + if doc.embedded? + parent = doc._parent + parent.inc(counter_name.to_sym => 1) if parent.respond_to? counter_name + else + relation = doc.send(name) + if relation && relation.class.fields.keys.include?(counter_name) + relation.inc(counter_name.to_sym => 1) + end end end end after_destroy do |doc| - if doc.embedded? - parent = doc._parent - parent.inc(counter_name.to_sym, -1) if parent.respond_to? counter_name - else - relation = doc.send(name) - if relation && relation.class.fields.keys.include?(counter_name) - relation.inc(counter_name.to_sym, -1) + result = condition.nil? ? true : condition.call(doc) + #if condition + # condition.each do |key, value| + # if doc.fields.keys.include?(key) and doc[key.to_sym] == value + # else + # result = false + # break + # end + # end + #end + + if result + if doc.embedded? + parent = doc._parent + parent.inc(counter_name.to_sym => -1) if parent.respond_to? counter_name + else + relation = doc.send(name) + if relation && relation.class.fields.keys.include?(counter_name) + relation.inc(counter_name.to_sym => -1) + end end end end diff --git a/spec/models/comment.rb b/spec/models/comment.rb new file mode 100644 index 0000000..e1c0280 --- /dev/null +++ b/spec/models/comment.rb @@ -0,0 +1,11 @@ +class Comment + include Mongoid::Document + include Mongoid::MagicCounterCache + + belongs_to :post + + field :remark + field :is_published, type: Mongoid::Boolean, default: false + + counter_cache :post, :if => Proc.new { |act| (act.is_published) } +end diff --git a/spec/models/post.rb b/spec/models/post.rb new file mode 100644 index 0000000..d7ddccb --- /dev/null +++ b/spec/models/post.rb @@ -0,0 +1,9 @@ +class Post + include Mongoid::Document + + field :article + field :comment_count, :type => Integer, :default => 0 + + has_many :comments + +end diff --git a/spec/mongoid/magic_counter_cache_spec.rb b/spec/mongoid/magic_counter_cache_spec.rb index 155dced..b5bd78f 100644 --- a/spec/mongoid/magic_counter_cache_spec.rb +++ b/spec/mongoid/magic_counter_cache_spec.rb @@ -6,7 +6,7 @@ module Mongoid describe ".counter_cache" do - context "when the document is associated" do + context "when the document is associatedi without condition" do before do Library.delete_all @@ -81,6 +81,7 @@ module Mongoid book.foreign_publication_count.should == 1 end + context "when the referenced document has an embedded document" do let(:page) do @@ -119,6 +120,7 @@ module Mongoid end end + context "when the document is embedded" do before do @@ -205,6 +207,79 @@ module Mongoid person.all_my_feels.should == person.feelings.size end end + + context "when the document is associated with condition" do + + before do + Post.delete_all + end + + let(:post) do + Post.new + end + + let(:comment) do + Comment.new(:is_published => true) + end + + before do + post.save + post.comments.create(:remark => "I agree with you", :is_published => true) + end + + it "sets the target of the relation" do + post.comments.first.remark.should == "I agree with you" + end + + it "should have 1 comment for post" do + post.comments.size.should == 1 + end + + it "should have 1 in comment counter" do + post.comment_count.should == 1 + end + + it "sets the counter cache equal to the relation count on addition" do + 5.times do |n| + post.comments << Comment.new(:is_published => true) + post.comment_count.should == post.comments.size + end + end + + it "should increase counter when new books are added" do + post.comments.push( comment ) + post.comments.size.should == 2 + end + + it "should increase counter when new books are added" do + post.comments.push( comment ) + post.comments.size.should == post.comment_count + end + + it "should decrease counter when published comment is deleted" do + post.comments.push( comment ) + comment.destroy + post.comments.size.should == 1 + end + + it "should increase counter when new books are added" do + post.comments.push( comment ) + comment.destroy + post.comments.size.should == post.comment_count + end + + it "shouldnot increase counter when unpublished comment is added" do + post.comments << Comment.new + post.comments.size.should == post.comment_count + 1 + end + + it "shouldnot decrease counter when unpublished comment is deleted" do + post.comments << Comment.new(:remark => "2nd comment") + post.comments << Comment.new(:remark => "3rd comment", :is_published => true) + Comment.where(:remark == "2nd comment").first.destroy + post.comment_count.should == 2 + end + end end end