activerecord-futures 0.3.0 → 0.4.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.
- 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
|