ar-octopus 0.8.1 → 0.10.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +6 -14
- data/.gitignore +1 -0
- data/.rspec +1 -1
- data/.rubocop.yml +46 -0
- data/.rubocop_todo.yml +56 -0
- data/.travis.yml +7 -12
- data/Appraisals +11 -4
- data/Gemfile +1 -1
- data/README.mkdn +138 -63
- data/Rakefile +23 -16
- data/ar-octopus.gemspec +23 -20
- data/gemfiles/rails42.gemfile +7 -0
- data/gemfiles/{rails32.gemfile → rails5.gemfile} +2 -2
- data/gemfiles/{rails4.gemfile → rails51.gemfile} +2 -2
- data/gemfiles/rails52.gemfile +7 -0
- data/lib/ar-octopus.rb +1 -1
- data/lib/octopus/{rails3/abstract_adapter.rb → abstract_adapter.rb} +4 -15
- data/lib/octopus/association.rb +8 -99
- data/lib/octopus/association_shard_tracking.rb +74 -0
- data/lib/octopus/collection_association.rb +17 -0
- data/lib/octopus/collection_proxy.rb +16 -0
- data/lib/octopus/exception.rb +4 -0
- data/lib/octopus/finder_methods.rb +8 -0
- data/lib/octopus/load_balancing/round_robin.rb +20 -0
- data/lib/octopus/load_balancing.rb +4 -0
- data/lib/octopus/{rails3/log_subscriber.rb → log_subscriber.rb} +6 -2
- data/lib/octopus/migration.rb +187 -110
- data/lib/octopus/model.rb +151 -131
- data/lib/octopus/persistence.rb +45 -0
- data/lib/octopus/proxy.rb +297 -232
- data/lib/octopus/proxy_config.rb +251 -0
- data/lib/octopus/query_cache_for_shards.rb +24 -0
- data/lib/octopus/railtie.rb +1 -3
- data/lib/octopus/relation_proxy.rb +70 -0
- data/lib/octopus/result_patch.rb +19 -0
- data/lib/octopus/scope_proxy.rb +54 -36
- data/lib/octopus/shard_tracking/attribute.rb +22 -0
- data/lib/octopus/shard_tracking/dynamic.rb +11 -0
- data/lib/octopus/shard_tracking.rb +46 -0
- data/lib/octopus/singular_association.rb +9 -0
- data/lib/octopus/slave_group.rb +13 -0
- data/lib/octopus/version.rb +1 -1
- data/lib/octopus.rb +125 -33
- data/lib/tasks/octopus.rake +2 -2
- data/sample_app/Gemfile +3 -3
- data/sample_app/autotest/discover.rb +2 -2
- data/sample_app/config/application.rb +1 -1
- data/sample_app/config/boot.rb +1 -1
- data/sample_app/config/environments/test.rb +1 -1
- data/sample_app/config/initializers/session_store.rb +1 -1
- data/sample_app/config/initializers/wrap_parameters.rb +1 -1
- data/sample_app/config/routes.rb +1 -1
- data/sample_app/db/migrate/20100720210335_create_sample_users.rb +2 -2
- data/sample_app/db/schema.rb +10 -10
- data/sample_app/db/seeds.rb +3 -3
- data/sample_app/features/step_definitions/seeds_steps.rb +4 -4
- data/sample_app/features/step_definitions/web_steps.rb +3 -4
- data/sample_app/features/support/env.rb +3 -4
- data/sample_app/features/support/paths.rb +4 -4
- data/sample_app/lib/tasks/cucumber.rake +43 -44
- data/sample_app/spec/spec_helper.rb +3 -3
- data/spec/config/shards.yml +78 -0
- data/spec/migrations/10_create_users_using_replication.rb +4 -4
- data/spec/migrations/11_add_field_in_all_slaves.rb +4 -4
- data/spec/migrations/12_create_users_using_block.rb +8 -8
- data/spec/migrations/13_create_users_using_block_and_using.rb +5 -5
- data/spec/migrations/14_create_users_on_shards_of_a_group_with_versions.rb +3 -3
- data/spec/migrations/15_create_user_on_shards_of_default_group_with_versions.rb +3 -3
- data/spec/migrations/1_create_users_on_master.rb +4 -4
- data/spec/migrations/2_create_users_on_canada.rb +4 -4
- data/spec/migrations/3_create_users_on_both_shards.rb +4 -4
- data/spec/migrations/4_create_users_on_shards_of_a_group.rb +4 -4
- data/spec/migrations/5_create_users_on_multiples_groups.rb +3 -3
- data/spec/migrations/6_raise_exception_with_invalid_shard_name.rb +4 -4
- data/spec/migrations/7_raise_exception_with_invalid_multiple_shard_names.rb +4 -4
- data/spec/migrations/8_raise_exception_with_invalid_group_name.rb +4 -4
- data/spec/migrations/9_raise_exception_with_multiple_invalid_group_names.rb +5 -5
- data/spec/octopus/association_shard_tracking_spec.rb +1036 -0
- data/spec/octopus/collection_proxy_spec.rb +16 -0
- data/spec/octopus/load_balancing/round_robin_spec.rb +15 -0
- data/spec/octopus/log_subscriber_spec.rb +5 -5
- data/spec/octopus/migration_spec.rb +83 -49
- data/spec/octopus/model_spec.rb +544 -292
- data/spec/octopus/octopus_spec.rb +64 -31
- data/spec/octopus/proxy_spec.rb +145 -141
- data/spec/octopus/query_cache_for_shards_spec.rb +40 -0
- data/spec/octopus/relation_proxy_spec.rb +132 -0
- data/spec/octopus/replicated_slave_grouped_spec.rb +91 -0
- data/spec/octopus/replication_spec.rb +140 -65
- data/spec/octopus/scope_proxy_spec.rb +90 -10
- data/spec/octopus/sharded_replicated_slave_grouped_spec.rb +55 -0
- data/spec/octopus/sharded_spec.rb +10 -10
- data/spec/spec_helper.rb +8 -6
- data/spec/support/active_record/connection_adapters/modify_config_adapter.rb +1 -3
- data/spec/support/database_connection.rb +2 -2
- data/spec/support/database_models.rb +18 -17
- data/spec/support/octopus_helper.rb +32 -25
- data/spec/support/query_count.rb +1 -3
- data/spec/support/shared_contexts.rb +3 -3
- data/spec/tasks/octopus.rake_spec.rb +10 -10
- metadata +112 -70
- data/.ruby-version +0 -1
- data/init.rb +0 -1
- data/lib/octopus/association_collection.rb +0 -49
- data/lib/octopus/has_and_belongs_to_many_association.rb +0 -17
- data/lib/octopus/rails3/persistence.rb +0 -39
- data/lib/octopus/rails3/singular_association.rb +0 -34
- data/rails/init.rb +0 -1
- data/spec/octopus/association_spec.rb +0 -712
data/lib/octopus.rb
CHANGED
@@ -2,24 +2,24 @@ require 'active_record'
|
|
2
2
|
require 'active_support/version'
|
3
3
|
require 'active_support/core_ext/class'
|
4
4
|
|
5
|
-
require
|
6
|
-
require
|
5
|
+
require 'yaml'
|
6
|
+
require 'erb'
|
7
7
|
|
8
8
|
module Octopus
|
9
|
-
def self.env
|
9
|
+
def self.env
|
10
10
|
@env ||= 'octopus'
|
11
11
|
end
|
12
12
|
|
13
|
-
def self.rails_env
|
14
|
-
@rails_env ||=
|
13
|
+
def self.rails_env
|
14
|
+
@rails_env ||= defined?(::Rails.env) ? Rails.env.to_s : 'shards'
|
15
15
|
end
|
16
16
|
|
17
17
|
def self.config
|
18
18
|
@config ||= begin
|
19
|
-
file_name = Octopus.directory
|
19
|
+
file_name = File.join(Octopus.directory, 'config/shards.yml').to_s
|
20
20
|
|
21
|
-
if File.
|
22
|
-
config ||= HashWithIndifferentAccess.new(YAML.load(ERB.new(File.read(file_name)).result))[Octopus.env
|
21
|
+
if File.exist?(file_name) || File.symlink?(file_name)
|
22
|
+
config ||= HashWithIndifferentAccess.new(YAML.load(ERB.new(File.read(file_name)).result))[Octopus.env]
|
23
23
|
else
|
24
24
|
config ||= HashWithIndifferentAccess.new
|
25
25
|
end
|
@@ -28,13 +28,25 @@ module Octopus
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
+
def self.load_balancer=(balancer)
|
32
|
+
@load_balancer = balancer
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.load_balancer
|
36
|
+
@load_balancer ||= Octopus::LoadBalancing::RoundRobin
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.master_shard
|
40
|
+
((config && config[:master_shard]) || :master).to_sym
|
41
|
+
end
|
42
|
+
|
31
43
|
# Public: Whether or not Octopus is configured and should hook into the
|
32
44
|
# current environment. Checks the environments config option for the Rails
|
33
45
|
# environment by default.
|
34
46
|
#
|
35
47
|
# Returns a boolean
|
36
48
|
def self.enabled?
|
37
|
-
if defined?(::Rails)
|
49
|
+
if defined?(::Rails.env)
|
38
50
|
Octopus.environments.include?(Rails.env.to_s)
|
39
51
|
else
|
40
52
|
# TODO: This doens't feel right but !Octopus.config.blank? is breaking a
|
@@ -45,8 +57,8 @@ module Octopus
|
|
45
57
|
|
46
58
|
# Returns the Rails.root_to_s when you are using rails
|
47
59
|
# Running the current directory in a generic Ruby process
|
48
|
-
def self.directory
|
49
|
-
@directory ||= defined?(Rails) ?
|
60
|
+
def self.directory
|
61
|
+
@directory ||= defined?(::Rails.root) ? Rails.root.to_s : Dir.pwd
|
50
62
|
end
|
51
63
|
|
52
64
|
# This is the default way to do Octopus Setup
|
@@ -57,27 +69,71 @@ module Octopus
|
|
57
69
|
end
|
58
70
|
|
59
71
|
def self.environments=(environments)
|
60
|
-
@environments = environments.map
|
72
|
+
@environments = environments.map(&:to_s)
|
61
73
|
end
|
62
74
|
|
63
75
|
def self.environments
|
64
76
|
@environments ||= config['environments'] || ['production']
|
65
77
|
end
|
66
78
|
|
67
|
-
def self.
|
68
|
-
|
79
|
+
def self.robust_environments=(environments)
|
80
|
+
@robust_environments = environments.map(&:to_s)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Environments in which to swallow failures from a single shard
|
84
|
+
# when iterating through all.
|
85
|
+
def self.robust_environments
|
86
|
+
@robust_environments ||= config['robust_environments'] || ['production']
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.robust_environment?
|
90
|
+
robust_environments.include? rails_env
|
69
91
|
end
|
70
92
|
|
71
93
|
def self.rails4?
|
72
|
-
ActiveRecord::VERSION::MAJOR
|
94
|
+
ActiveRecord::VERSION::MAJOR == 4
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.rails42?
|
98
|
+
rails4? && ActiveRecord::VERSION::MINOR == 2
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.rails50?
|
102
|
+
ActiveRecord::VERSION::MAJOR == 5 && ActiveRecord::VERSION::MINOR == 0
|
103
|
+
end
|
104
|
+
|
105
|
+
def self.atleast_rails50?
|
106
|
+
ActiveRecord::VERSION::MAJOR >= 5
|
107
|
+
end
|
108
|
+
|
109
|
+
def self.rails51?
|
110
|
+
ActiveRecord::VERSION::MAJOR == 5 && ActiveRecord::VERSION::MINOR == 1
|
73
111
|
end
|
74
112
|
|
75
|
-
def self.
|
76
|
-
|
113
|
+
def self.rails52?
|
114
|
+
ActiveRecord::VERSION::MAJOR == 5 && ActiveRecord::VERSION::MINOR == 2
|
115
|
+
end
|
116
|
+
|
117
|
+
def self.atleast_rails51?
|
118
|
+
ActiveRecord::VERSION::MAJOR > 5 || (ActiveRecord::VERSION::MAJOR == 5 && ActiveRecord::VERSION::MINOR >= 1)
|
119
|
+
end
|
120
|
+
|
121
|
+
def self.atleast_rails52?
|
122
|
+
ActiveRecord::VERSION::MAJOR > 5 || (ActiveRecord::VERSION::MAJOR == 5 && ActiveRecord::VERSION::MINOR > 1)
|
123
|
+
end
|
124
|
+
|
125
|
+
attr_writer :logger
|
126
|
+
|
127
|
+
def self.logger
|
128
|
+
if defined?(Rails.logger)
|
129
|
+
@logger ||= Rails.logger
|
130
|
+
else
|
131
|
+
@logger ||= Logger.new($stderr)
|
132
|
+
end
|
77
133
|
end
|
78
134
|
|
79
135
|
def self.shards=(shards)
|
80
|
-
config[rails_env
|
136
|
+
config[rails_env] = HashWithIndifferentAccess.new(shards)
|
81
137
|
ActiveRecord::Base.connection.initialize_shards(@config)
|
82
138
|
end
|
83
139
|
|
@@ -90,23 +146,59 @@ module Octopus
|
|
90
146
|
yield
|
91
147
|
end
|
92
148
|
end
|
93
|
-
end
|
94
149
|
|
150
|
+
def self.using_group(group, &block)
|
151
|
+
conn = ActiveRecord::Base.connection
|
95
152
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
require "octopus/rails3/log_subscriber"
|
103
|
-
require "octopus/rails3/abstract_adapter"
|
104
|
-
require "octopus/rails3/singular_association"
|
153
|
+
if conn.is_a?(Octopus::Proxy)
|
154
|
+
conn.send_queries_to_group(group, &block)
|
155
|
+
else
|
156
|
+
yield
|
157
|
+
end
|
158
|
+
end
|
105
159
|
|
106
|
-
|
107
|
-
|
108
|
-
|
160
|
+
def self.using_all(&block)
|
161
|
+
conn = ActiveRecord::Base.connection
|
162
|
+
|
163
|
+
if conn.is_a?(Octopus::Proxy)
|
164
|
+
conn.send_queries_to_all_shards(&block)
|
165
|
+
else
|
166
|
+
yield
|
167
|
+
end
|
168
|
+
end
|
109
169
|
|
170
|
+
def self.fully_replicated(&_block)
|
171
|
+
old_fully_replicated = Thread.current[Octopus::ProxyConfig::FULLY_REPLICATED_KEY]
|
172
|
+
Thread.current[Octopus::ProxyConfig::FULLY_REPLICATED_KEY] = true
|
173
|
+
yield
|
174
|
+
ensure
|
175
|
+
Thread.current[Octopus::ProxyConfig::FULLY_REPLICATED_KEY] = old_fully_replicated
|
176
|
+
end
|
177
|
+
end
|
110
178
|
|
111
|
-
require
|
112
|
-
|
179
|
+
require 'octopus/exception'
|
180
|
+
|
181
|
+
require 'octopus/shard_tracking'
|
182
|
+
require 'octopus/shard_tracking/attribute'
|
183
|
+
require 'octopus/shard_tracking/dynamic'
|
184
|
+
|
185
|
+
require 'octopus/model'
|
186
|
+
require 'octopus/result_patch'
|
187
|
+
require 'octopus/migration'
|
188
|
+
require 'octopus/association'
|
189
|
+
require 'octopus/collection_association'
|
190
|
+
require 'octopus/association_shard_tracking'
|
191
|
+
require 'octopus/persistence'
|
192
|
+
require 'octopus/log_subscriber'
|
193
|
+
require 'octopus/abstract_adapter'
|
194
|
+
require 'octopus/singular_association'
|
195
|
+
require 'octopus/finder_methods'
|
196
|
+
require 'octopus/query_cache_for_shards' unless Octopus.rails4?
|
197
|
+
|
198
|
+
require 'octopus/railtie' if defined?(::Rails::Railtie)
|
199
|
+
|
200
|
+
require 'octopus/proxy_config'
|
201
|
+
require 'octopus/proxy'
|
202
|
+
require 'octopus/collection_proxy'
|
203
|
+
require 'octopus/relation_proxy'
|
204
|
+
require 'octopus/scope_proxy'
|
data/lib/tasks/octopus.rake
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
namespace :octopus do
|
2
|
-
desc
|
2
|
+
desc 'Copy schema version information from master to all shards'
|
3
3
|
task :copy_schema_versions => :environment do
|
4
|
-
abort(
|
4
|
+
abort('Octopus is not enabled for this environment') unless Octopus.enabled?
|
5
5
|
|
6
6
|
connection = ActiveRecord::Base.connection
|
7
7
|
|
data/sample_app/Gemfile
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
Autotest.add_discovery {
|
2
|
-
Autotest.add_discovery {
|
1
|
+
Autotest.add_discovery { 'rails' }
|
2
|
+
Autotest.add_discovery { 'rspec2' }
|
@@ -34,7 +34,7 @@ module SampleApp
|
|
34
34
|
# config.i18n.default_locale = :de
|
35
35
|
|
36
36
|
# Configure the default encoding used in templates for Ruby 1.9.
|
37
|
-
config.encoding =
|
37
|
+
config.encoding = 'utf-8'
|
38
38
|
|
39
39
|
# Configure sensitive parameters which will be filtered from the log file.
|
40
40
|
config.filter_parameters += [:password]
|
data/sample_app/config/boot.rb
CHANGED
@@ -9,7 +9,7 @@ SampleApp::Application.configure do
|
|
9
9
|
|
10
10
|
# Configure static asset server for tests with Cache-Control for performance
|
11
11
|
config.serve_static_assets = true
|
12
|
-
config.static_cache_control =
|
12
|
+
config.static_cache_control = 'public, max-age=3600'
|
13
13
|
|
14
14
|
# Log error messages when you accidentally call methods on nil
|
15
15
|
config.whiny_nils = true
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Be sure to restart your server when you modify this file.
|
2
2
|
|
3
|
-
SampleApp::Application.config.session_store :cookie_store, key
|
3
|
+
SampleApp::Application.config.session_store :cookie_store, :key => '_sample_app_session'
|
4
4
|
|
5
5
|
# Use the database for sessions instead of the cookie-based default,
|
6
6
|
# which shouldn't be used to store highly confidential information
|
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
|
7
7
|
ActiveSupport.on_load(:action_controller) do
|
8
|
-
wrap_parameters format
|
8
|
+
wrap_parameters :format => [:json]
|
9
9
|
end
|
10
10
|
|
11
11
|
# Disable root element in JSON by default.
|
data/sample_app/config/routes.rb
CHANGED
@@ -2,10 +2,10 @@ class CreateSampleUsers < ActiveRecord::Migration
|
|
2
2
|
using(:master, :asia, :europe, :america)
|
3
3
|
|
4
4
|
def self.up
|
5
|
-
User.create!(:name =>
|
5
|
+
User.create!(:name => 'Exception')
|
6
6
|
end
|
7
7
|
|
8
8
|
def self.down
|
9
|
-
User.find_by_name(
|
9
|
+
User.find_by_name('Exception').delete
|
10
10
|
end
|
11
11
|
end
|
data/sample_app/db/schema.rb
CHANGED
@@ -11,19 +11,19 @@
|
|
11
11
|
#
|
12
12
|
# It's strongly recommended to check this file into your version control system.
|
13
13
|
|
14
|
-
ActiveRecord::Schema.define(:version =>
|
14
|
+
ActiveRecord::Schema.define(:version => 20_100_720_210_335) do
|
15
15
|
|
16
|
-
create_table
|
17
|
-
t.string
|
18
|
-
t.integer
|
19
|
-
t.datetime
|
20
|
-
t.datetime
|
16
|
+
create_table 'items', :force => true do |t|
|
17
|
+
t.string 'name'
|
18
|
+
t.integer 'user_id'
|
19
|
+
t.datetime 'created_at', :null => false
|
20
|
+
t.datetime 'updated_at', :null => false
|
21
21
|
end
|
22
22
|
|
23
|
-
create_table
|
24
|
-
t.string
|
25
|
-
t.datetime
|
26
|
-
t.datetime
|
23
|
+
create_table 'users', :force => true do |t|
|
24
|
+
t.string 'name'
|
25
|
+
t.datetime 'created_at', :null => false
|
26
|
+
t.datetime 'updated_at', :null => false
|
27
27
|
end
|
28
28
|
|
29
29
|
end
|
data/sample_app/db/seeds.rb
CHANGED
@@ -6,11 +6,11 @@
|
|
6
6
|
# cities = City.create([{ :name => 'Chicago' }, { :name => 'Copenhagen' }])
|
7
7
|
# Mayor.create(:name => 'Daley', :city => cities.first)
|
8
8
|
Octopus.using(:asia) do
|
9
|
-
User.create!(:name =>
|
9
|
+
User.create!(:name => 'Asia User')
|
10
10
|
end
|
11
11
|
|
12
12
|
Octopus.using(:america) do
|
13
|
-
|
13
|
+
User.create([{ :name => 'America User 1' }, { :name => 'America User 2' }])
|
14
14
|
end
|
15
15
|
|
16
|
-
User.create!(:name =>
|
16
|
+
User.create!(:name => 'Teste')
|
@@ -3,11 +3,11 @@ Then /^the "([^"]*)" shard should have one user named "([^"]*)"$/ do |shard_name
|
|
3
3
|
end
|
4
4
|
|
5
5
|
Then /^the version of "([^"]*)" shard should be "([^"]*)"$/ do |shard_name, version|
|
6
|
-
ab = ActiveRecord::Base.using(shard_name.to_sym).connection.select_value(
|
7
|
-
version =
|
6
|
+
ab = ActiveRecord::Base.using(shard_name.to_sym).connection.select_value('select * from schema_migrations order by version desc limit 1;')
|
7
|
+
version = '' if version == 'nil'
|
8
8
|
ab.to_s.should == version
|
9
9
|
end
|
10
10
|
|
11
11
|
When /^I run inside my Rails project "([^"]*)" with enviroment "([^"]*)"$/ do |command, enviroment|
|
12
|
-
run("cd #{Rails.root
|
13
|
-
end
|
12
|
+
run("cd #{Rails.root} && RAILS_ENV=#{enviroment} #{command}")
|
13
|
+
end
|
@@ -4,10 +4,9 @@
|
|
4
4
|
# instead of editing this one. Cucumber will automatically load all features/**/*.rb
|
5
5
|
# files.
|
6
6
|
|
7
|
-
|
8
7
|
require 'uri'
|
9
8
|
require 'cgi'
|
10
|
-
require File.expand_path(File.join(File.dirname(__FILE__),
|
9
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'support', 'paths'))
|
11
10
|
|
12
11
|
module WithinHelpers
|
13
12
|
def with_scope(locator)
|
@@ -62,7 +61,7 @@ end
|
|
62
61
|
When /^(?:|I )fill in the following(?: within "([^"]*)")?:$/ do |selector, fields|
|
63
62
|
with_scope(selector) do
|
64
63
|
fields.rows_hash.each do |name, value|
|
65
|
-
When %
|
64
|
+
When %(I fill in "#{name}" with "#{value}")
|
66
65
|
end
|
67
66
|
end
|
68
67
|
end
|
@@ -205,7 +204,7 @@ Then /^(?:|I )should have the following query string:$/ do |expected_pairs|
|
|
205
204
|
query = URI.parse(current_url).query
|
206
205
|
actual_params = query ? CGI.parse(query) : {}
|
207
206
|
expected_params = {}
|
208
|
-
expected_pairs.rows_hash.each_pair{|k,v| expected_params[k] = v.split(',')}
|
207
|
+
expected_pairs.rows_hash.each_pair { |k, v| expected_params[k] = v.split(',') }
|
209
208
|
|
210
209
|
if actual_params.respond_to? :should
|
211
210
|
actual_params.should == expected_params
|
@@ -12,8 +12,8 @@ require 'cucumber/rails'
|
|
12
12
|
# Capybara.default_selector = :xpath
|
13
13
|
|
14
14
|
# By default, any exception happening in your Rails application will bubble up
|
15
|
-
# to Cucumber so that your scenario will fail. This is a different from how
|
16
|
-
# your application behaves in the production environment, where an error page will
|
15
|
+
# to Cucumber so that your scenario will fail. This is a different from how
|
16
|
+
# your application behaves in the production environment, where an error page will
|
17
17
|
# be rendered instead.
|
18
18
|
#
|
19
19
|
# Sometimes we want to override this default behaviour and allow Rails to rescue
|
@@ -33,7 +33,7 @@ ActionController::Base.allow_rescue = false
|
|
33
33
|
begin
|
34
34
|
DatabaseCleaner.strategy = :transaction
|
35
35
|
rescue NameError
|
36
|
-
raise
|
36
|
+
raise 'You need to add database_cleaner to your Gemfile (in the :test group) if you wish to use it.'
|
37
37
|
end
|
38
38
|
|
39
39
|
# You may also want to configure DatabaseCleaner to use different strategies for certain features and scenarios.
|
@@ -55,4 +55,3 @@ end
|
|
55
55
|
# The :transaction strategy is faster, but might give you threading problems.
|
56
56
|
# See https://github.com/cucumber/cucumber-rails/blob/master/features/choose_javascript_database_strategy.feature
|
57
57
|
Cucumber::Rails::Database.javascript_strategy = :truncation
|
58
|
-
|
@@ -20,10 +20,10 @@ module NavigationHelpers
|
|
20
20
|
else
|
21
21
|
begin
|
22
22
|
page_name =~ /the (.*) page/
|
23
|
-
path_components =
|
24
|
-
|
25
|
-
rescue
|
26
|
-
raise "Can't find mapping from \"#{page_name}\" to a path.\n"
|
23
|
+
path_components = Regexp.last_match[1].split(/\s+/)
|
24
|
+
send(path_components.push('path').join('_').to_sym)
|
25
|
+
rescue
|
26
|
+
raise "Can't find mapping from \"#{page_name}\" to a path.\n" \
|
27
27
|
"Now, go and add a mapping in #{__FILE__}"
|
28
28
|
end
|
29
29
|
end
|
@@ -4,62 +4,61 @@
|
|
4
4
|
# instead of editing this one. Cucumber will automatically load all features/**/*.rb
|
5
5
|
# files.
|
6
6
|
|
7
|
+
unless ARGV.any? { |a| a =~ /^gems/ } # Don't load anything when running the gems:* tasks
|
7
8
|
|
8
|
-
|
9
|
+
vendored_cucumber_bin = Dir["#{Rails.root}/vendor/{gems,plugins}/cucumber*/bin/cucumber"].first
|
10
|
+
$LOAD_PATH.unshift(File.dirname(vendored_cucumber_bin) + '/../lib') unless vendored_cucumber_bin.nil?
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
+
begin
|
13
|
+
require 'cucumber/rake/task'
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
+
namespace :cucumber do
|
16
|
+
Cucumber::Rake::Task.new({ :ok => 'test:prepare' }, 'Run features that should pass') do |t|
|
17
|
+
t.binary = vendored_cucumber_bin # If nil, the gem's binary is used.
|
18
|
+
t.fork = true # You may get faster startup if you set this to false
|
19
|
+
t.profile = 'default'
|
20
|
+
end
|
15
21
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
Cucumber::Rake::Task.new({:wip => 'test:prepare'}, 'Run features that are being worked on') do |t|
|
24
|
-
t.binary = vendored_cucumber_bin
|
25
|
-
t.fork = true # You may get faster startup if you set this to false
|
26
|
-
t.profile = 'wip'
|
27
|
-
end
|
22
|
+
Cucumber::Rake::Task.new({ :wip => 'test:prepare' }, 'Run features that are being worked on') do |t|
|
23
|
+
t.binary = vendored_cucumber_bin
|
24
|
+
t.fork = true # You may get faster startup if you set this to false
|
25
|
+
t.profile = 'wip'
|
26
|
+
end
|
28
27
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
28
|
+
Cucumber::Rake::Task.new({ :rerun => 'test:prepare' }, 'Record failing features and run only them if any exist') do |t|
|
29
|
+
t.binary = vendored_cucumber_bin
|
30
|
+
t.fork = true # You may get faster startup if you set this to false
|
31
|
+
t.profile = 'rerun'
|
32
|
+
end
|
34
33
|
|
35
|
-
|
36
|
-
|
34
|
+
desc 'Run all features'
|
35
|
+
task :all => [:ok, :wip]
|
37
36
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
task :statsetup do
|
38
|
+
require 'rails/code_statistics'
|
39
|
+
::STATS_DIRECTORIES << %w(Cucumber\ features features) if File.exist?('features')
|
40
|
+
::CodeStatistics::TEST_TYPES << 'Cucumber features' if File.exist?('features')
|
41
|
+
end
|
42
42
|
end
|
43
|
-
|
44
|
-
|
45
|
-
task :cucumber => 'cucumber:ok'
|
43
|
+
desc 'Alias for cucumber:ok'
|
44
|
+
task :cucumber => 'cucumber:ok'
|
46
45
|
|
47
|
-
|
46
|
+
task :default => :cucumber
|
48
47
|
|
49
|
-
|
50
|
-
|
51
|
-
|
48
|
+
task :features => :cucumber do
|
49
|
+
STDERR.puts "*** The 'features' task is deprecated. See rake -T cucumber ***"
|
50
|
+
end
|
52
51
|
|
53
|
-
|
54
|
-
|
55
|
-
|
52
|
+
# In case we don't have the generic Rails test:prepare hook, append a no-op task that we can depend upon.
|
53
|
+
task 'test:prepare' do
|
54
|
+
end
|
56
55
|
|
57
|
-
|
58
|
-
rescue LoadError
|
59
|
-
|
60
|
-
|
61
|
-
|
56
|
+
task :stats => 'cucumber:statsetup'
|
57
|
+
rescue LoadError
|
58
|
+
desc 'cucumber rake task not available (cucumber not installed)'
|
59
|
+
task :cucumber do
|
60
|
+
abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin'
|
61
|
+
end
|
62
62
|
end
|
63
|
-
end
|
64
63
|
|
65
64
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
# This file is copied to ~/spec when you run 'ruby script/generate rspec'
|
2
2
|
# from the project root directory.
|
3
|
-
ENV[
|
4
|
-
require File.expand_path(
|
3
|
+
ENV['RAILS_ENV'] ||= 'test'
|
4
|
+
require File.expand_path('../../config/environment', __FILE__)
|
5
5
|
require 'rspec/rails'
|
6
6
|
|
7
7
|
# Requires supporting files with custom matchers and macros, etc,
|
8
8
|
# in ./support/ and its subdirectories.
|
9
|
-
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
9
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
10
10
|
|
11
11
|
RSpec.configure do |config|
|
12
12
|
# == Mock Framework
|