ar-async-counter-cache 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -0,0 +1,68 @@
1
+ ar-async-counter-cache
2
+ ----------------------
3
+
4
+ This gem allows you to update ActiveRecord counter cache columns
5
+ asynchronously. You may want to do this in situations where you want really
6
+ speedy inserts and have models that "belong_to" many different parents.
7
+
8
+ You use it like such:
9
+
10
+ class User < ActiveRecord::Base
11
+ has_many :comments
12
+ has_many :posts
13
+ end
14
+
15
+ class Post < ActiveRecord::Base
16
+ belongs_to :user, :async_counter_cache => true
17
+ has_many :comments
18
+ end
19
+
20
+ class Comment < ActiveRecord::Base
21
+ belongs_to :user, :async_counter_cache => true
22
+ belongs_to :post, :async_counter_cache => "count_of_comments"
23
+ end
24
+
25
+ Notice, you may specify the name of the counter cache column just as you can
26
+ with the normal belongs_to :counter_cache option. You also may not use both
27
+ the :async_counter_cache and :counter_cache options in the same belongs_to
28
+ call.
29
+
30
+ All you should need to do is require this gem in your project that uses
31
+ ActiveRecord and you should be good to go;
32
+
33
+ e.g. In your Gemfile:
34
+
35
+ gem 'ar-async-counter-cache', '0.0.1'
36
+
37
+ and then in RAILS_ROOT/config/environment.rb somewhere:
38
+
39
+ require 'ar-async-counter-cache'
40
+
41
+ This gem has built-in support for Resque (http://github.com/defunkt/resque).
42
+ Al you need is resque in your loadpath:
43
+
44
+ e.g. In your Gemfile:
45
+
46
+ gem 'resque', '1.9.4'
47
+
48
+ By default, the Resque job is placed on the :default queue:
49
+
50
+ @queue = :default
51
+
52
+ However, you can change this:
53
+
54
+ in RAILS_ROOT/config/environment.rb somewhere:
55
+
56
+ ArAsyncCounterCache.resque_job_queue = :low_priority
57
+
58
+ If you don't want to use Resque, you must define one instance method for your
59
+ models using ar-async-counter-cache:
60
+
61
+ e.g.:
62
+
63
+ Comment#async_increment_counters
64
+
65
+ That method should pass a message onto a queue for a background processor to
66
+ handle later. That background processor should call:
67
+
68
+ Comment#update_async_counters(:increment)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.2
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ar-async-counter-cache}
8
- s.version = "0.0.1"
8
+ s.version = "0.0.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Aaron Gibralter"]
@@ -22,7 +22,8 @@ Gem::Specification.new do |s|
22
22
  "ar-async-counter-cache.gemspec",
23
23
  "lib/ar-async-counter-cache.rb",
24
24
  "lib/ar_async_counter_cache/active_record.rb",
25
- "lib/ar_async_counter_cache/resque_job.rb",
25
+ "lib/ar_async_counter_cache/increment_counters_job.rb",
26
+ "pkg/ar-async-counter-cache-0.0.1.gem",
26
27
  "spec/ar_async_counter_cache/active_record_spec.rb",
27
28
  "spec/integration_spec.rb",
28
29
  "spec/models.rb",
@@ -32,7 +33,7 @@ Gem::Specification.new do |s|
32
33
  s.homepage = %q{http://github.com/agibralter/ar-async-counter-cache}
33
34
  s.rdoc_options = ["--charset=UTF-8"]
34
35
  s.require_paths = ["lib"]
35
- s.rubygems_version = %q{1.3.7}
36
+ s.rubygems_version = %q{1.3.6}
36
37
  s.summary = %q{Increment ActiveRecord's counter cache column asynchronously (using Resque).}
37
38
  s.test_files = [
38
39
  "spec/ar_async_counter_cache/active_record_spec.rb",
@@ -45,7 +46,7 @@ Gem::Specification.new do |s|
45
46
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
46
47
  s.specification_version = 3
47
48
 
48
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
49
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
49
50
  s.add_runtime_dependency(%q<activerecord>, [">= 2.3.5"])
50
51
  else
51
52
  s.add_dependency(%q<activerecord>, [">= 2.3.5"])
@@ -1,10 +1,11 @@
1
+ require 'active_record'
2
+
1
3
  begin
2
4
  require 'resque'
3
- require 'ar_async_counter_cache/resque_job'
5
+ require 'ar_async_counter_cache/increment_counters_job'
4
6
  rescue LoadError
5
7
  end
6
8
 
7
- require 'active_record'
8
9
  require 'ar_async_counter_cache/active_record'
9
10
 
10
11
  ActiveRecord::Base.send(:include, ArAsyncCounterCache::ActiveRecord)
@@ -9,13 +9,6 @@ module ArAsyncCounterCache
9
9
  }.gsub(/\s+/, ' ').strip
10
10
  end
11
11
 
12
- def async_decrement_counters
13
- raise %{
14
- Since you don't have resque installed, please define #{self.class.to_s}#async_decrement_counters.
15
- Basically it should queue a job that calls #{self.class.to_s}#update_async_counters(:decrement).
16
- }.gsub(/\s+/, ' ').strip
17
- end
18
-
19
12
  def update_async_counters(dir, *parent_types)
20
13
  (parent_types.empty? ? self.class.async_counter_types.keys : parent_types).each do |parent_type|
21
14
  if (col = self.class.async_counter_types[parent_type]) && (parent = send(parent_type))
@@ -53,9 +46,9 @@ module ArAsyncCounterCache
53
46
  def add_callbacks
54
47
  # Define after_create callback method.
55
48
  method_name = "belongs_to_async_counter_cache_after_create".to_sym
56
- if defined?(ArAsyncCounterCache::UpdateCountersJob)
49
+ if defined?(ArAsyncCounterCache::IncrementCountersJob)
57
50
  define_method(method_name) do
58
- Resque.enqueue(ArAsyncCounterCache::UpdateCountersJob, self.class.to_s, self.id, :increment)
51
+ Resque.enqueue(ArAsyncCounterCache::IncrementCountersJob, self.class.to_s, self.id)
59
52
  end
60
53
  else
61
54
  define_method(method_name) do
@@ -65,14 +58,8 @@ module ArAsyncCounterCache
65
58
  after_create(method_name)
66
59
  # Define before_destroy callback method.
67
60
  method_name = "belongs_to_async_counter_cache_before_destroy".to_sym
68
- if defined?(ArAsyncCounterCache::UpdateCountersJob)
69
- define_method(method_name) do
70
- Resque.enqueue(ArAsyncCounterCache::UpdateCountersJob, self.class.to_s, self.id, :decrement)
71
- end
72
- else
73
- define_method(method_name) do
74
- self.async_decrement_counters
75
- end
61
+ define_method(method_name) do
62
+ update_async_counters(:decrement)
76
63
  end
77
64
  before_destroy(method_name)
78
65
  end
@@ -1,25 +1,26 @@
1
1
  module ArAsyncCounterCache
2
2
 
3
3
  def self.resque_job_queue=(sym)
4
- ArAsyncCounterCache::UpdateCountersJob.class_eval do
4
+ ArAsyncCounterCache::IncrementCountersJob.class_eval do
5
5
  @queue = sym
6
6
  end
7
7
  end
8
8
 
9
- class UpdateCountersJob
9
+ class IncrementCountersJob
10
10
  @queue = :default
11
11
 
12
12
  # Take advantage of resque-retry if possible.
13
13
  begin
14
14
  require 'resque-retry'
15
+ require 'active_record/base'
15
16
  extend Resque::Plugins::ExponentialBackoff
16
- @retry_exceptions = [ActiveRecord::RecordNotFound]
17
+ @retry_exceptions = [::ActiveRecord::RecordNotFound]
17
18
  @backoff_strategy = [0, 10, 100]
18
19
  rescue LoadError
19
20
  end
20
21
 
21
- def self.perform(klass_name, id, dir)
22
- Object.const_get(klass_name).find(id).update_async_counters(dir)
22
+ def self.perform(klass_name, id)
23
+ Object.const_get(klass_name).find(id).update_async_counters(:increment)
23
24
  end
24
25
  end
25
26
  end
@@ -16,7 +16,7 @@ describe ArAsyncCounterCache::ActiveRecord do
16
16
  end
17
17
 
18
18
  it "should queue job" do
19
- Resque.should_receive(:enqueue).with(ArAsyncCounterCache::UpdateCountersJob, "Post", an_instance_of(Fixnum), :increment)
19
+ Resque.should_receive(:enqueue).with(ArAsyncCounterCache::IncrementCountersJob, "Post", an_instance_of(Fixnum))
20
20
  @user.posts.create(:body => "I have a cat!")
21
21
  end
22
22
  end
@@ -44,11 +44,11 @@ describe "integration" do
44
44
  @post2.reload.count_of_comments.should == 1
45
45
  end
46
46
 
47
- it "should decrement too" do
47
+ it "should decrement synchronously" do
48
+ perform_all_jobs
48
49
  @comment1.destroy
49
50
  @comment2.destroy
50
51
  @comment3.destroy
51
- perform_all_jobs
52
52
  @user1.reload.posts_count.should == 2
53
53
  @user1.reload.comments_count.should == 0
54
54
  @user2.reload.posts_count.should == 0
data/spec/spec_helper.rb CHANGED
@@ -1,13 +1,10 @@
1
1
  spec_dir = File.expand_path(File.dirname(__FILE__))
2
-
3
- $: << File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
4
- $: << spec_dir
2
+ $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')))
5
3
 
6
4
  require 'rubygems'
7
5
  # Ensure resque for tests.
8
6
  require 'resque'
9
7
  require 'ar-async-counter-cache'
10
-
11
8
  require 'spec'
12
9
  require 'models'
13
10
 
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ar-async-counter-cache
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
5
4
  prerelease: false
6
5
  segments:
7
6
  - 0
8
7
  - 0
9
- - 1
10
- version: 0.0.1
8
+ - 2
9
+ version: 0.0.2
11
10
  platform: ruby
12
11
  authors:
13
12
  - Aaron Gibralter
@@ -22,11 +21,9 @@ dependencies:
22
21
  name: activerecord
23
22
  prerelease: false
24
23
  requirement: &id001 !ruby/object:Gem::Requirement
25
- none: false
26
24
  requirements:
27
25
  - - ">="
28
26
  - !ruby/object:Gem::Version
29
- hash: 9
30
27
  segments:
31
28
  - 2
32
29
  - 3
@@ -49,7 +46,8 @@ files:
49
46
  - ar-async-counter-cache.gemspec
50
47
  - lib/ar-async-counter-cache.rb
51
48
  - lib/ar_async_counter_cache/active_record.rb
52
- - lib/ar_async_counter_cache/resque_job.rb
49
+ - lib/ar_async_counter_cache/increment_counters_job.rb
50
+ - pkg/ar-async-counter-cache-0.0.1.gem
53
51
  - spec/ar_async_counter_cache/active_record_spec.rb
54
52
  - spec/integration_spec.rb
55
53
  - spec/models.rb
@@ -65,27 +63,23 @@ rdoc_options:
65
63
  require_paths:
66
64
  - lib
67
65
  required_ruby_version: !ruby/object:Gem::Requirement
68
- none: false
69
66
  requirements:
70
67
  - - ">="
71
68
  - !ruby/object:Gem::Version
72
- hash: 3
73
69
  segments:
74
70
  - 0
75
71
  version: "0"
76
72
  required_rubygems_version: !ruby/object:Gem::Requirement
77
- none: false
78
73
  requirements:
79
74
  - - ">="
80
75
  - !ruby/object:Gem::Version
81
- hash: 3
82
76
  segments:
83
77
  - 0
84
78
  version: "0"
85
79
  requirements: []
86
80
 
87
81
  rubyforge_project:
88
- rubygems_version: 1.3.7
82
+ rubygems_version: 1.3.6
89
83
  signing_key:
90
84
  specification_version: 3
91
85
  summary: Increment ActiveRecord's counter cache column asynchronously (using Resque).