activerecord-futures 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. data/README.md +34 -8
  2. data/lib/active_record/connection_adapters/future_enabled.rb +6 -5
  3. data/lib/active_record/connection_adapters/future_enabled_mysql2_adapter.rb +2 -1
  4. data/lib/active_record/connection_adapters/future_enabled_postgresql_adapter.rb +21 -7
  5. data/lib/active_record/futures.rb +11 -23
  6. data/lib/active_record/futures/calculation_methods.rb +34 -0
  7. data/lib/active_record/futures/delegation.rb +1 -1
  8. data/lib/active_record/futures/finder_methods.rb +59 -0
  9. data/lib/active_record/futures/future.rb +21 -57
  10. data/lib/active_record/futures/future_array.rb +23 -0
  11. data/lib/active_record/futures/future_registry.rb +33 -0
  12. data/lib/active_record/futures/future_value.rb +20 -0
  13. data/lib/active_record/futures/query_recording.rb +11 -4
  14. data/lib/activerecord-futures.rb +5 -4
  15. data/lib/activerecord-futures/version.rb +1 -1
  16. data/spec/active_record/futures/future_array_spec.rb +26 -0
  17. data/spec/active_record/futures/future_registry_spec.rb +86 -0
  18. data/spec/active_record/futures/future_spec.rb +42 -69
  19. data/spec/active_record/futures/future_value_spec.rb +26 -0
  20. data/spec/in_action/combination_of_futures_spec.rb +13 -9
  21. data/spec/in_action/future_all_execution_spec.rb +20 -0
  22. data/spec/in_action/future_count_execution_spec.rb +8 -56
  23. data/spec/in_action/future_exists_execution_spec.rb +22 -0
  24. data/spec/in_action/future_find_execution_spec.rb +68 -0
  25. data/spec/in_action/future_first_execution_spec.rb +20 -0
  26. data/spec/in_action/future_fulfillment_spec.rb +10 -7
  27. data/spec/in_action/future_last_execution_spec.rb +21 -0
  28. data/spec/in_action/future_pluck_execution_spec.rb +4 -27
  29. data/spec/in_action/future_relation_execution_spec.rb +8 -30
  30. data/spec/spec_helper.rb +2 -1
  31. data/spec/support/futurized_method_examples.rb +43 -0
  32. metadata +25 -12
  33. data/lib/active_record/futures/future_calculation.rb +0 -30
  34. data/lib/active_record/futures/future_calculation_array.rb +0 -8
  35. data/lib/active_record/futures/future_calculation_value.rb +0 -7
  36. data/lib/active_record/futures/future_relation.rb +0 -34
  37. data/spec/active_record/futures/future_calculation_array_spec.rb +0 -29
  38. data/spec/active_record/futures/future_calculation_value_spec.rb +0 -29
  39. data/spec/active_record/futures/future_relation_spec.rb +0 -81
@@ -3,8 +3,9 @@ require 'spec_helper'
3
3
  describe "future_count method" do
4
4
  context "single value count" do
5
5
  let(:relation) { Post.where("published_at < ?", Time.new(2013, 1, 1)) }
6
- let(:count) { relation.future_count }
7
- let(:count_sql) do
6
+ let(:future) { relation.future_count }
7
+ let(:relation_result) { relation.count }
8
+ let(:future_sql) do
8
9
  arel = relation.arel
9
10
  arel.projections = []
10
11
  arel.project("COUNT(*)")
@@ -17,37 +18,14 @@ describe "future_count method" do
17
18
  Post.create(published_at: Time.new(2013, 4, 5))
18
19
  end
19
20
 
20
- describe "#value" do
21
- let(:calling_value) { -> { count.value } }
22
-
23
- specify do
24
- calling_value.should exec(1).query
25
- end
26
-
27
- specify do
28
- calling_value.should exec_query(count_sql)
29
- end
30
-
31
- specify { count.value.should eq 2 }
32
-
33
- context "executing it twice" do
34
- before do
35
- count.value
36
- end
37
-
38
- specify do
39
- calling_value.should exec(0).queries
40
- end
41
-
42
- specify { count.value.should eq 2 }
43
- end
44
- end
21
+ it_behaves_like "a futurized method", :value
45
22
  end
46
23
 
47
24
  context "grouped value count" do
48
25
  let(:relation) { Comment.scoped }
49
- let(:count) { relation.future_count(group: :post_id) }
50
- let(:count_sql) do
26
+ let(:future) { relation.future_count(group: :post_id) }
27
+ let(:relation_result) { relation.count(group: :post_id) }
28
+ let(:future_sql) do
51
29
  arel = relation.arel
52
30
  arel.projections = []
53
31
  arel.project("COUNT(*) AS count_all")
@@ -67,32 +45,6 @@ describe "future_count method" do
67
45
  Comment.create(post: post_2)
68
46
  end
69
47
 
70
- describe "#value" do
71
- let(:calling_value) { -> { count.value } }
72
-
73
- specify do
74
- calling_value.should exec(1).query
75
- end
76
-
77
- specify do
78
- calling_value.should exec_query(count_sql)
79
- end
80
-
81
- specify { count.value[post_1.id].should eq 2 }
82
- specify { count.value[post_2.id].should eq 3 }
83
-
84
- context "executing it twice" do
85
- before do
86
- count.value
87
- end
88
-
89
- specify do
90
- calling_value.should exec(0).queries
91
- end
92
-
93
- specify { count.value[post_1.id].should eq 2 }
94
- specify { count.value[post_2.id].should eq 3 }
95
- end
96
- end
48
+ it_behaves_like "a futurized method", :value
97
49
  end
98
50
  end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe "future_exists? method" do
4
+ let(:relation) { Post.where("published_at < ?", Time.new(2013, 1, 1)) }
5
+ let(:future) { relation.future_exists? }
6
+ let(:relation_result) { relation.exists? }
7
+ let(:future_sql) do
8
+ arel = relation.arel
9
+ arel.projections = []
10
+ arel.project("1 AS one")
11
+ arel.limit = 1
12
+ arel.to_sql
13
+ end
14
+
15
+ before do
16
+ Post.create(published_at: Time.new(2012, 12, 10))
17
+ Post.create(published_at: Time.new(2012, 6, 23))
18
+ Post.create(published_at: Time.new(2013, 4, 5))
19
+ end
20
+
21
+ it_behaves_like "a futurized method", :value
22
+ end
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+
3
+ describe "future_find method" do
4
+ context "finding by a single id" do
5
+ let(:relation) { Post.where("published_at < ?", Time.new(2013, 1, 1)) }
6
+ let(:future) { relation.future_find(@post_id) }
7
+ let(:relation_result) { relation.find(@post_id) }
8
+ let(:future_sql) do
9
+ arel = relation.where(id: @post_id).arel
10
+ arel.limit = 1
11
+ arel.to_sql
12
+ end
13
+
14
+ let(:future_sql_postgresql) do
15
+ arel = relation.arel
16
+ arel.constraints.unshift(Arel.sql('"posts"."id" = $1'))
17
+ arel.limit = 1
18
+ arel.to_sql
19
+ end
20
+
21
+ before do
22
+ Post.create(published_at: Time.new(2012, 12, 10))
23
+ Post.create(published_at: Time.new(2012, 6, 23))
24
+ Post.create(published_at: Time.new(2013, 4, 5))
25
+ @post_id = relation.first.id
26
+ end
27
+
28
+ it_behaves_like "a futurized method", :value
29
+ end
30
+
31
+ context "finding by multiple ids" do
32
+ let(:relation) { Post.where("published_at < ?", Time.new(2013, 1, 1)) }
33
+ let(:future) { relation.future_find(*@post_ids) }
34
+ let(:relation_result) { relation.find(*@post_ids) }
35
+ let(:future_sql) do
36
+ arel = relation.where(id: @post_ids).arel
37
+ arel.to_sql
38
+ end
39
+
40
+ before do
41
+ Post.create(published_at: Time.new(2012, 12, 10))
42
+ Post.create(published_at: Time.new(2012, 6, 23))
43
+ Post.create(published_at: Time.new(2013, 4, 5))
44
+ @post_ids = [relation.first.id, relation.last.id]
45
+ end
46
+
47
+ it_behaves_like "a futurized method", :to_a
48
+ end
49
+
50
+ context "finding by multiple ids, with single array parameter" do
51
+ let(:relation) { Post.where("published_at < ?", Time.new(2013, 1, 1)) }
52
+ let(:future) { relation.future_find(@post_ids) }
53
+ let(:relation_result) { relation.find(@post_ids) }
54
+ let(:future_sql) do
55
+ arel = relation.where(id: @post_ids).arel
56
+ arel.to_sql
57
+ end
58
+
59
+ before do
60
+ Post.create(published_at: Time.new(2012, 12, 10))
61
+ Post.create(published_at: Time.new(2012, 6, 23))
62
+ Post.create(published_at: Time.new(2013, 4, 5))
63
+ @post_ids = [relation.first.id, relation.last.id]
64
+ end
65
+
66
+ it_behaves_like "a futurized method", :to_a
67
+ end
68
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe "future_first method" do
4
+ let(:relation) { Post.where("published_at < ?", Time.new(2013, 1, 1)) }
5
+ let(:future) { relation.future_first }
6
+ let(:relation_result) { relation.first }
7
+ let(:future_sql) do
8
+ arel = relation.arel
9
+ arel.limit = 1
10
+ arel.to_sql
11
+ end
12
+
13
+ before do
14
+ Post.create(published_at: Time.new(2012, 12, 10))
15
+ Post.create(published_at: Time.new(2012, 6, 23))
16
+ Post.create(published_at: Time.new(2013, 4, 5))
17
+ end
18
+
19
+ it_behaves_like "a futurized method", :value
20
+ end
@@ -2,19 +2,20 @@ require "spec_helper"
2
2
 
3
3
  module ActiveRecord::Futures
4
4
  describe "Future fulfillment" do
5
- subject { Future }
5
+ subject { FutureRegistry }
6
6
 
7
7
  context "when futurizing a relation" do
8
- let!(:future) { Post.where(title: "Some post").future }
8
+ let!(:future_result) { Post.where(title: "Some post").future }
9
+ let!(:future) { future_result.send(:future_execution) }
9
10
 
10
11
  its(:all) { should have(1).future }
11
12
 
12
- context "the relation future" do
13
+ context "the future" do
13
14
  specify { future.should_not be_fulfilled }
14
15
  end
15
16
 
16
17
  context "and executing it" do
17
- before { future.to_a }
18
+ before { future_result.to_a }
18
19
 
19
20
  its(:all) { should have(0).futures }
20
21
 
@@ -28,8 +29,10 @@ module ActiveRecord::Futures
28
29
  end
29
30
 
30
31
  context "when futurizing two relations" do
31
- let!(:future) { Post.where(title: "Some post").future }
32
- let!(:another_future) { User.where(name: "Lenny").future }
32
+ let!(:future_result) { Post.where(title: "Some post").future }
33
+ let!(:future) { future_result.send(:future_execution) }
34
+ let!(:another_future_result) { User.where(name: "Lenny").future }
35
+ let!(:another_future) { another_future_result.send(:future_execution) }
33
36
 
34
37
  its(:all) { should have(2).futures }
35
38
 
@@ -42,7 +45,7 @@ module ActiveRecord::Futures
42
45
  end
43
46
 
44
47
  context "and executing one of them" do
45
- before { future.to_a }
48
+ before { future_result.to_a }
46
49
 
47
50
  its(:all) { should have(0).futures }
48
51
 
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe "future_last method" do
4
+ let(:relation) { Post.where("published_at < ?", Time.new(2013, 1, 1)) }
5
+ let(:future) { relation.future_last }
6
+ let(:relation_result) { relation.last }
7
+ let(:future_sql) do
8
+ arel = relation.arel
9
+ arel.order("#{relation.quoted_table_name}.#{relation.quoted_primary_key} DESC")
10
+ arel.limit = 1
11
+ arel.to_sql
12
+ end
13
+
14
+ before do
15
+ Post.create(published_at: Time.new(2012, 12, 10))
16
+ Post.create(published_at: Time.new(2012, 6, 23))
17
+ Post.create(published_at: Time.new(2013, 4, 5))
18
+ end
19
+
20
+ it_behaves_like "a futurized method", :value
21
+ end
@@ -2,8 +2,9 @@ require 'spec_helper'
2
2
 
3
3
  describe "future_pluck method" do
4
4
  let(:relation) { Post.where("published_at < ?", Time.new(2013, 1, 1)) }
5
- let(:pluck) { relation.future_pluck('title') }
6
- let(:pluck_sql) do
5
+ let(:future) { relation.future_pluck('title') }
6
+ let(:relation_result) { relation.pluck('title') }
7
+ let(:future_sql) do
7
8
  arel = relation.arel
8
9
  arel.projections = []
9
10
  arel.project('title')
@@ -16,29 +17,5 @@ describe "future_pluck method" do
16
17
  Post.create(title: "Post 3", published_at: Time.new(2013, 4, 5))
17
18
  end
18
19
 
19
- describe "#to_a" do
20
- let(:calling_to_a) { -> { pluck.to_a } }
21
-
22
- specify do
23
- calling_to_a.should exec(1).query
24
- end
25
-
26
- specify do
27
- calling_to_a.should exec_query(pluck_sql)
28
- end
29
-
30
- specify { pluck.to_a.should eq ["Post 1", "Post 2"] }
31
-
32
- context "executing it twice" do
33
- before do
34
- pluck.to_a
35
- end
36
-
37
- specify do
38
- calling_to_a.should exec(0).queries
39
- end
40
-
41
- specify { pluck.to_a.should eq ["Post 1", "Post 2"] }
42
- end
43
- end
20
+ it_behaves_like "a futurized method", :to_a
44
21
  end
@@ -8,45 +8,23 @@ describe "future method" do
8
8
  Post.create(published_at: Time.new(2013, 4, 5))
9
9
  end
10
10
 
11
- def self.spec_relation(description, relation_lambda, &block)
11
+ def self.test_case(description, &relation_lambda)
12
12
  context "with a sample relation that #{description}" do
13
13
  let(:relation) { relation_lambda.call }
14
+ let(:relation_result) { relation.to_a }
14
15
  let(:future) { relation.future }
16
+ let(:future_sql) { relation.to_sql }
15
17
 
16
- describe "#to_a" do
17
- let(:calling_to_a) { lambda { future.to_a } }
18
-
19
- specify do
20
- calling_to_a.should exec(1).query
21
- end
22
-
23
- specify do
24
- calling_to_a.should exec_query(relation.to_sql)
25
- end
26
-
27
- instance_eval(&block)
28
-
29
- context "executing it twice" do
30
- before do
31
- future.to_a
32
- end
33
-
34
- specify do
35
- calling_to_a.should exec(0).queries
36
- end
37
-
38
- instance_eval(&block)
39
- end
40
- end
18
+ it_behaves_like "a futurized method", :to_a
41
19
  end
42
20
  end
43
21
 
44
- spec_relation "filters by published_at", -> { Post.where("published_at < ?", Time.new(2013, 1, 1)) } do
45
- specify { future.to_a.should have(2).posts }
22
+ test_case "filters by published_at" do
23
+ Post.where("published_at < ?", Time.new(2013, 1, 1))
46
24
  end
47
25
 
48
- spec_relation "limits by 10", -> { Post.limit(10) } do
49
- specify { future.to_a.should have(3).posts }
26
+ test_case "limits by 10" do
27
+ Post.limit(10)
50
28
  end
51
29
 
52
30
  end
data/spec/spec_helper.rb CHANGED
@@ -50,6 +50,7 @@ RSpec.configure do |config|
50
50
  config.run_all_when_everything_filtered = true
51
51
  config.filter_run :focus
52
52
  config.filter_run_excluding(supports_futures ? :not_supporting_adapter : :supporting_adapter)
53
+ config.filter_run_excluding(postgresql: config_key.to_s.include?("postgresql") ? false : true)
53
54
  # Run specs in random order to surface order dependencies. If you find an
54
55
  # order dependency and want to debug it, you can fix the order by providing
55
56
  # the seed, which is printed after each run.
@@ -64,6 +65,6 @@ RSpec.configure do |config|
64
65
  end
65
66
 
66
67
  config.after do
67
- ActiveRecord::Futures::Future.clear
68
+ ActiveRecord::Futures::FutureRegistry.clear
68
69
  end
69
70
  end
@@ -0,0 +1,43 @@
1
+ shared_examples "a futurized method" do |exec_trigger|
2
+ describe "##{exec_trigger}" do
3
+ let(:future_execution) { future.send(:future_execution) }
4
+ let(:calling_future) { -> { future.send(exec_trigger) } }
5
+
6
+ specify(nil, :supporting_adapter) { future_execution.should_not be_fulfilled }
7
+
8
+ specify do
9
+ calling_future.should exec(1).query
10
+ end
11
+
12
+ specify(nil, postgresql: false) do
13
+ calling_future.should exec_query(future_sql)
14
+ end
15
+
16
+ specify(nil, postgresql: true) do
17
+ sql = respond_to?(:future_sql_postgresql) ? future_sql_postgresql : future_sql
18
+ calling_future.should exec_query(sql)
19
+ end
20
+
21
+ specify { future.send(exec_trigger).should eq relation_result }
22
+
23
+ context "after executing the future" do
24
+ before do
25
+ future.send(exec_trigger)
26
+ end
27
+
28
+ specify(nil, :supporting_adapter) { future_execution.should be_fulfilled }
29
+ end
30
+
31
+ context "executing it twice" do
32
+ before do
33
+ future.send(exec_trigger)
34
+ end
35
+
36
+ specify do
37
+ calling_future.should exec(0).queries
38
+ end
39
+
40
+ specify { future.send(exec_trigger).should eq relation_result }
41
+ end
42
+ end
43
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-futures
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-05-03 00:00:00.000000000 Z
12
+ date: 2013-05-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -110,31 +110,38 @@ files:
110
110
  - lib/active_record/connection_adapters/future_enabled_mysql2_adapter.rb
111
111
  - lib/active_record/connection_adapters/future_enabled_postgresql_adapter.rb
112
112
  - lib/active_record/futures.rb
113
+ - lib/active_record/futures/calculation_methods.rb
113
114
  - lib/active_record/futures/delegation.rb
115
+ - lib/active_record/futures/finder_methods.rb
114
116
  - lib/active_record/futures/future.rb
115
- - lib/active_record/futures/future_calculation.rb
116
- - lib/active_record/futures/future_calculation_array.rb
117
- - lib/active_record/futures/future_calculation_value.rb
118
- - lib/active_record/futures/future_relation.rb
117
+ - lib/active_record/futures/future_array.rb
118
+ - lib/active_record/futures/future_registry.rb
119
+ - lib/active_record/futures/future_value.rb
119
120
  - lib/active_record/futures/proxy.rb
120
121
  - lib/active_record/futures/query_recording.rb
121
122
  - lib/activerecord-futures.rb
122
123
  - lib/activerecord-futures/version.rb
123
- - spec/active_record/futures/future_calculation_array_spec.rb
124
- - spec/active_record/futures/future_calculation_value_spec.rb
125
- - spec/active_record/futures/future_relation_spec.rb
124
+ - spec/active_record/futures/future_array_spec.rb
125
+ - spec/active_record/futures/future_registry_spec.rb
126
126
  - spec/active_record/futures/future_spec.rb
127
+ - spec/active_record/futures/future_value_spec.rb
127
128
  - spec/active_record/futures/proxy_spec.rb
128
129
  - spec/db/schema.rb
129
130
  - spec/in_action/combination_of_futures_spec.rb
131
+ - spec/in_action/future_all_execution_spec.rb
130
132
  - spec/in_action/future_count_execution_spec.rb
133
+ - spec/in_action/future_exists_execution_spec.rb
134
+ - spec/in_action/future_find_execution_spec.rb
135
+ - spec/in_action/future_first_execution_spec.rb
131
136
  - spec/in_action/future_fulfillment_spec.rb
137
+ - spec/in_action/future_last_execution_spec.rb
132
138
  - spec/in_action/future_pluck_execution_spec.rb
133
139
  - spec/in_action/future_relation_execution_spec.rb
134
140
  - spec/models/comment.rb
135
141
  - spec/models/post.rb
136
142
  - spec/models/user.rb
137
143
  - spec/spec_helper.rb
144
+ - spec/support/futurized_method_examples.rb
138
145
  - spec/support/matchers/exec.rb
139
146
  - spec/support/matchers/exec_query.rb
140
147
  homepage: https://github.com/leoasis/activerecord-futures
@@ -162,21 +169,27 @@ signing_key:
162
169
  specification_version: 3
163
170
  summary: Fetch all queries at once from the database and save round trips.
164
171
  test_files:
165
- - spec/active_record/futures/future_calculation_array_spec.rb
166
- - spec/active_record/futures/future_calculation_value_spec.rb
167
- - spec/active_record/futures/future_relation_spec.rb
172
+ - spec/active_record/futures/future_array_spec.rb
173
+ - spec/active_record/futures/future_registry_spec.rb
168
174
  - spec/active_record/futures/future_spec.rb
175
+ - spec/active_record/futures/future_value_spec.rb
169
176
  - spec/active_record/futures/proxy_spec.rb
170
177
  - spec/db/schema.rb
171
178
  - spec/in_action/combination_of_futures_spec.rb
179
+ - spec/in_action/future_all_execution_spec.rb
172
180
  - spec/in_action/future_count_execution_spec.rb
181
+ - spec/in_action/future_exists_execution_spec.rb
182
+ - spec/in_action/future_find_execution_spec.rb
183
+ - spec/in_action/future_first_execution_spec.rb
173
184
  - spec/in_action/future_fulfillment_spec.rb
185
+ - spec/in_action/future_last_execution_spec.rb
174
186
  - spec/in_action/future_pluck_execution_spec.rb
175
187
  - spec/in_action/future_relation_execution_spec.rb
176
188
  - spec/models/comment.rb
177
189
  - spec/models/post.rb
178
190
  - spec/models/user.rb
179
191
  - spec/spec_helper.rb
192
+ - spec/support/futurized_method_examples.rb
180
193
  - spec/support/matchers/exec.rb
181
194
  - spec/support/matchers/exec_query.rb
182
195
  has_rdoc: