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 CHANGED
@@ -3,6 +3,7 @@
3
3
  .bundle
4
4
  .config
5
5
  .yardoc
6
+ *.sqlite3
6
7
  Gemfile.lock
7
8
  InstalledFiles
8
9
  _yardoc
@@ -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=future_enabled_postgresql activerecord=3.2.11
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
- Once the gem is installed, set your config/database.yml file to use a future enabled adapter:
37
-
38
- ```yml
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 `to_a` method, or the delegated ones, and those that return a value or a hash
103
- are triggered with the `value` method. Note that the `find` method returns an
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 `send_query` method
125
- and retrieving the results via `get_result`.
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 future_enabled_postgresql postgresql 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
@@ -22,4 +22,5 @@ Gem::Specification.new do |gem|
22
22
  gem.add_development_dependency 'rspec-spies'
23
23
  gem.add_development_dependency 'mysql2', '>= 0.3.12.b1'
24
24
  gem.add_development_dependency 'pg'
25
+ gem.add_development_dependency 'sqlite3'
25
26
  end
@@ -0,0 +1,14 @@
1
+ module ActiveRecord
2
+ module Futures
3
+ class Middleware
4
+ def initialize(app)
5
+ @app = app
6
+ end
7
+
8
+ def call(env)
9
+ FutureRegistry.clear
10
+ @app.call(env)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,7 @@
1
+ module ActiveRecord
2
+ module Futures
3
+ class Railtie < ::Rails::Railtie
4
+ config.app_middleware.use Middleware
5
+ end
6
+ end
7
+ end
@@ -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
@@ -1,5 +1,5 @@
1
1
  module Activerecord
2
2
  module Futures
3
- VERSION = "0.3.0"
3
+ VERSION = "0.4.0"
4
4
  end
5
5
  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))
@@ -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: "future_enabled_mysql2",
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
- config.filter_run_excluding(postgresql: config_key.to_s.include?("postgresql") ? false : true)
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.3.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-13 00:00:00.000000000 Z
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