activerecord-futures 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/.travis.yml +5 -6
- data/README.md +21 -14
- data/Rakefile +1 -1
- data/activerecord-futures.gemspec +1 -0
- data/lib/active_record/futures/middleware.rb +14 -0
- data/lib/active_record/futures/railtie.rb +7 -0
- data/lib/activerecord-futures.rb +30 -0
- data/lib/activerecord-futures/version.rb +1 -1
- data/spec/active_record/futures/middleware_spec.rb +43 -0
- data/spec/in_action/future_find_execution_spec.rb +7 -0
- data/spec/spec_helper.rb +16 -7
- data/spec/support/futurized_method_examples.rb +6 -1
- metadata +22 -2
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -2,18 +2,17 @@ language: ruby
|
|
2
2
|
rvm:
|
3
3
|
- 1.9.3
|
4
4
|
env:
|
5
|
-
- ADAPTER=future_enabled_mysql2 activerecord=3.2.11
|
6
|
-
- ADAPTER=future_enabled_mysql2 activerecord=3.2.12
|
7
|
-
- ADAPTER=future_enabled_mysql2 activerecord=3.2.13
|
8
5
|
- ADAPTER=mysql2 activerecord=3.2.11
|
9
6
|
- ADAPTER=mysql2 activerecord=3.2.12
|
10
7
|
- ADAPTER=mysql2 activerecord=3.2.13
|
11
|
-
- ADAPTER=
|
12
|
-
- ADAPTER=future_enabled_postgresql activerecord=3.2.12
|
13
|
-
- ADAPTER=future_enabled_postgresql activerecord=3.2.13
|
8
|
+
- ADAPTER=future_enabled_mysql2 activerecord=3.2.13
|
14
9
|
- ADAPTER=postgresql activerecord=3.2.11
|
15
10
|
- ADAPTER=postgresql activerecord=3.2.12
|
16
11
|
- ADAPTER=postgresql activerecord=3.2.13
|
12
|
+
- ADAPTER=future_enabled_postgresql activerecord=3.2.13
|
13
|
+
- ADAPTER=sqlite3 activerecord=3.2.11
|
14
|
+
- ADAPTER=sqlite3 activerecord=3.2.12
|
15
|
+
- ADAPTER=sqlite3 activerecord=3.2.13
|
17
16
|
|
18
17
|
before_script:
|
19
18
|
- mysql -e 'create database activerecord_futures_test;'
|
data/README.md
CHANGED
@@ -33,16 +33,9 @@ Or install it yourself as:
|
|
33
33
|
|
34
34
|
## Usage
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
development: &development
|
40
|
-
adapter: future_enabled_mysql2 # or "future_enabled_postgresql"
|
41
|
-
username: your_username
|
42
|
-
password: your_password
|
43
|
-
database: your_database
|
44
|
-
host: your_host
|
45
|
-
```
|
36
|
+
If you're using postgresql or mysql2 currently, you have nothing more to do. The gem will automatically use the future enabled adapter and just work. If you are using a custom adapter, specify it in the config/database.yml file as you're used to.
|
37
|
+
|
38
|
+
Check the database support (below) section for more info.
|
46
39
|
|
47
40
|
Now let's see what this does, consider a model `User`, with a `:name` attribute:
|
48
41
|
|
@@ -66,6 +59,20 @@ Any amount of futures can be prepared, and they will get executed as soon as one
|
|
66
59
|
This makes this especially useful for pagination queries, since you can execute
|
67
60
|
both count and page queries at once.
|
68
61
|
|
62
|
+
#### Rails
|
63
|
+
|
64
|
+
No configuration to do, things will Just Work.
|
65
|
+
|
66
|
+
#### Rack based apps (not Rails)
|
67
|
+
|
68
|
+
You will need to manually add the `ActiveRecord::Futures::Middleware` somewhere in the middleware stack:
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
use ActiveRecord::Futures::Middleware
|
72
|
+
```
|
73
|
+
|
74
|
+
This is to clear the futures that were defined and not triggered between requests.
|
75
|
+
|
69
76
|
### Methods
|
70
77
|
|
71
78
|
#### #future method
|
@@ -99,8 +106,8 @@ Lastly, you also get finder methods futurized, which are:
|
|
99
106
|
* future_all
|
100
107
|
|
101
108
|
As with the other future methods, those which return an array get triggered with
|
102
|
-
the
|
103
|
-
are triggered with the
|
109
|
+
the `#to_a` method, or the delegated ones, and those that return a value or a hash
|
110
|
+
are triggered with the `#value` method. Note that the `#find` method returns an
|
104
111
|
array or a value depending on the parameters provided, and so will the futurized
|
105
112
|
version of the method.
|
106
113
|
|
@@ -121,8 +128,8 @@ If you have an older version of the gem, ActiveRecord::Futures will fall back to
|
|
121
128
|
|
122
129
|
### Postgres
|
123
130
|
|
124
|
-
The pg gem supports multiple statement queries by using the
|
125
|
-
and retrieving the results via
|
131
|
+
The pg gem supports multiple statement queries by using the `#send_query` method
|
132
|
+
and retrieving the results via `#get_result`.
|
126
133
|
|
127
134
|
### Other databases
|
128
135
|
|
data/Rakefile
CHANGED
@@ -5,7 +5,7 @@ RSpec::Core::RakeTask.new(:spec)
|
|
5
5
|
|
6
6
|
task :default => :spec
|
7
7
|
|
8
|
-
ADAPTERS = %w(future_enabled_mysql2
|
8
|
+
ADAPTERS = %w(future_enabled_postgresql future_enabled_mysql2 postgresql mysql2 sqlite3)
|
9
9
|
|
10
10
|
desc "Runs the specs with all databases"
|
11
11
|
task :all do
|
data/lib/activerecord-futures.rb
CHANGED
@@ -14,6 +14,9 @@ require "active_record/futures/calculation_methods"
|
|
14
14
|
require "active_record/futures"
|
15
15
|
require "active_record/futures/delegation"
|
16
16
|
|
17
|
+
require "active_record/futures/middleware" if defined?(Rack)
|
18
|
+
require "active_record/futures/railtie" if defined?(Rails)
|
19
|
+
|
17
20
|
module ActiveRecord
|
18
21
|
class Relation
|
19
22
|
include Futures
|
@@ -22,4 +25,31 @@ module ActiveRecord
|
|
22
25
|
class Base
|
23
26
|
extend Futures::Delegation
|
24
27
|
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class ActiveRecord::Base::ConnectionSpecification
|
31
|
+
class Resolver
|
32
|
+
def spec_with_futures
|
33
|
+
spec = spec_without_futures
|
34
|
+
begin
|
35
|
+
config = spec.config
|
36
|
+
future_adapter_name = "future_enabled_#{config[:adapter]}"
|
37
|
+
|
38
|
+
# Try to load the future version of the adapter
|
39
|
+
require "active_record/connection_adapters/#{future_adapter_name}_adapter"
|
40
|
+
|
41
|
+
config[:adapter] = future_adapter_name
|
42
|
+
adapter_method = "future_enabled_#{spec.adapter_method}"
|
43
|
+
|
44
|
+
# Return the specification with the future adapter instead
|
45
|
+
ActiveRecord::Base::ConnectionSpecification.new(config, adapter_method)
|
46
|
+
rescue LoadError
|
47
|
+
# No future version of the adapter, or the adapter was already a future
|
48
|
+
# one. Keep going as usual...
|
49
|
+
spec
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
alias_method_chain :spec, :futures
|
54
|
+
end
|
25
55
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'active_record/futures/middleware'
|
3
|
+
|
4
|
+
module ActiveRecord::Futures
|
5
|
+
describe Middleware do
|
6
|
+
let(:app) { double("Rack Application", call: nil) }
|
7
|
+
let(:env) { double("App environment") }
|
8
|
+
|
9
|
+
subject(:middleware) { Middleware.new(app) }
|
10
|
+
|
11
|
+
before do
|
12
|
+
FutureRegistry.stub(:clear)
|
13
|
+
end
|
14
|
+
|
15
|
+
context "normal flow" do
|
16
|
+
before do
|
17
|
+
middleware.call(env)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "resets the registry" do
|
21
|
+
FutureRegistry.should have_received(:clear)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "continues calling the middleware stack" do
|
25
|
+
app.should have_received(:call).with(env)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "when app.call raises exception" do
|
30
|
+
before do
|
31
|
+
app.stub(:call).and_raise("some error")
|
32
|
+
begin
|
33
|
+
middleware.call(env)
|
34
|
+
rescue
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it "still clears the registry" do
|
39
|
+
FutureRegistry.should have_received(:clear)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -18,6 +18,13 @@ describe "future_find method" do
|
|
18
18
|
arel.to_sql
|
19
19
|
end
|
20
20
|
|
21
|
+
let(:future_sql_sqlite3) do
|
22
|
+
arel = relation.arel
|
23
|
+
arel.constraints.unshift(Arel.sql('"posts"."id" = ?'))
|
24
|
+
arel.limit = 1
|
25
|
+
arel.to_sql
|
26
|
+
end
|
27
|
+
|
21
28
|
before do
|
22
29
|
Post.create(published_at: Time.new(2012, 12, 10))
|
23
30
|
Post.create(published_at: Time.new(2012, 6, 23))
|
data/spec/spec_helper.rb
CHANGED
@@ -4,17 +4,17 @@ Coveralls.wear!
|
|
4
4
|
require 'activerecord-futures'
|
5
5
|
|
6
6
|
configs = {
|
7
|
+
future_enabled_postgresql: {
|
8
|
+
adapter: "postgresql",
|
9
|
+
database: "activerecord_futures_test",
|
10
|
+
username: "postgres"
|
11
|
+
},
|
7
12
|
future_enabled_mysql2: {
|
8
|
-
adapter: "
|
13
|
+
adapter: "mysql2",
|
9
14
|
database: "activerecord_futures_test",
|
10
15
|
username: "root",
|
11
16
|
encoding: "utf8"
|
12
17
|
},
|
13
|
-
future_enabled_postgresql: {
|
14
|
-
adapter: "future_enabled_postgresql",
|
15
|
-
database: "activerecord_futures_test",
|
16
|
-
username: "postgres"
|
17
|
-
},
|
18
18
|
postgresql: {
|
19
19
|
adapter: "postgresql",
|
20
20
|
database: "activerecord_futures_test",
|
@@ -25,6 +25,10 @@ configs = {
|
|
25
25
|
database: "activerecord_futures_test",
|
26
26
|
username: "root",
|
27
27
|
encoding: "utf8"
|
28
|
+
},
|
29
|
+
sqlite3: {
|
30
|
+
adapter: "sqlite3",
|
31
|
+
database: ':memory:'
|
28
32
|
}
|
29
33
|
}
|
30
34
|
|
@@ -38,6 +42,8 @@ supports_futures =
|
|
38
42
|
ActiveRecord::Base.connection.respond_to?(:supports_futures?) &&
|
39
43
|
ActiveRecord::Base.connection.supports_futures?
|
40
44
|
|
45
|
+
puts "Supports futures!" if supports_futures
|
46
|
+
|
41
47
|
require 'db/schema'
|
42
48
|
Dir['./spec/models/**/*.rb'].each { |f| require f }
|
43
49
|
|
@@ -50,7 +56,10 @@ RSpec.configure do |config|
|
|
50
56
|
config.run_all_when_everything_filtered = true
|
51
57
|
config.filter_run :focus
|
52
58
|
config.filter_run_excluding(supports_futures ? :not_supporting_adapter : :supporting_adapter)
|
53
|
-
|
59
|
+
|
60
|
+
%w(postgresql mysql2 sqlite3).each do |adapter|
|
61
|
+
config.filter_run_excluding(adapter.to_sym => !config_key.to_s.include?(adapter))
|
62
|
+
end
|
54
63
|
# Run specs in random order to surface order dependencies. If you find an
|
55
64
|
# order dependency and want to debug it, you can fix the order by providing
|
56
65
|
# the seed, which is printed after each run.
|
@@ -9,7 +9,7 @@ shared_examples "a futurized method" do |exec_trigger|
|
|
9
9
|
calling_future.should exec(1).query
|
10
10
|
end
|
11
11
|
|
12
|
-
specify(nil, postgresql: false) do
|
12
|
+
specify(nil, postgresql: false, sqlite3: false) do
|
13
13
|
calling_future.should exec_query(future_sql)
|
14
14
|
end
|
15
15
|
|
@@ -18,6 +18,11 @@ shared_examples "a futurized method" do |exec_trigger|
|
|
18
18
|
calling_future.should exec_query(sql)
|
19
19
|
end
|
20
20
|
|
21
|
+
specify(nil, sqlite3: true) do
|
22
|
+
sql = respond_to?(:future_sql_sqlite3) ? future_sql_sqlite3 : future_sql
|
23
|
+
calling_future.should exec_query(sql)
|
24
|
+
end
|
25
|
+
|
21
26
|
specify { future.send(exec_trigger).should eq relation_result }
|
22
27
|
|
23
28
|
context "after executing the future" do
|
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.
|
4
|
+
version: 0.4.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-
|
12
|
+
date: 2013-05-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -91,6 +91,22 @@ dependencies:
|
|
91
91
|
- - ! '>='
|
92
92
|
- !ruby/object:Gem::Version
|
93
93
|
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: sqlite3
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
94
110
|
description: Save unnecessary round trips to the database
|
95
111
|
email:
|
96
112
|
- leoasis@gmail.com
|
@@ -117,14 +133,17 @@ files:
|
|
117
133
|
- lib/active_record/futures/future_array.rb
|
118
134
|
- lib/active_record/futures/future_registry.rb
|
119
135
|
- lib/active_record/futures/future_value.rb
|
136
|
+
- lib/active_record/futures/middleware.rb
|
120
137
|
- lib/active_record/futures/proxy.rb
|
121
138
|
- lib/active_record/futures/query_recording.rb
|
139
|
+
- lib/active_record/futures/railtie.rb
|
122
140
|
- lib/activerecord-futures.rb
|
123
141
|
- lib/activerecord-futures/version.rb
|
124
142
|
- spec/active_record/futures/future_array_spec.rb
|
125
143
|
- spec/active_record/futures/future_registry_spec.rb
|
126
144
|
- spec/active_record/futures/future_spec.rb
|
127
145
|
- spec/active_record/futures/future_value_spec.rb
|
146
|
+
- spec/active_record/futures/middleware_spec.rb
|
128
147
|
- spec/active_record/futures/proxy_spec.rb
|
129
148
|
- spec/db/schema.rb
|
130
149
|
- spec/in_action/combination_of_futures_spec.rb
|
@@ -173,6 +192,7 @@ test_files:
|
|
173
192
|
- spec/active_record/futures/future_registry_spec.rb
|
174
193
|
- spec/active_record/futures/future_spec.rb
|
175
194
|
- spec/active_record/futures/future_value_spec.rb
|
195
|
+
- spec/active_record/futures/middleware_spec.rb
|
176
196
|
- spec/active_record/futures/proxy_spec.rb
|
177
197
|
- spec/db/schema.rb
|
178
198
|
- spec/in_action/combination_of_futures_spec.rb
|