ar-octopus 0.0.26 → 0.0.27
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/Rakefile +9 -2
- data/ar-octopus.gemspec +70 -5
- data/lib/octopus/has_and_belongs_to_many_association.rb +1 -5
- data/lib/octopus/model.rb +6 -16
- data/lib/octopus/proxy.rb +1 -6
- data/lib/octopus/scope_proxy.rb +7 -10
- data/sample_app/.gitignore +4 -0
- data/sample_app/.rspec +1 -0
- data/sample_app/Gemfile +22 -0
- data/sample_app/Gemfile.lock +149 -0
- data/sample_app/README +3 -0
- data/sample_app/Rakefile +7 -0
- data/sample_app/app/controllers/application_controller.rb +4 -0
- data/sample_app/app/helpers/application_helper.rb +2 -0
- data/sample_app/app/models/item.rb +2 -0
- data/sample_app/app/models/user.rb +2 -0
- data/sample_app/app/views/layouts/application.html.erb +14 -0
- data/sample_app/autotest/discover.rb +2 -0
- data/sample_app/config.ru +4 -0
- data/sample_app/config/application.rb +46 -0
- data/sample_app/config/boot.rb +13 -0
- data/sample_app/config/cucumber.yml +8 -0
- data/sample_app/config/database.yml +25 -0
- data/sample_app/config/environment.rb +5 -0
- data/sample_app/config/environments/development.rb +19 -0
- data/sample_app/config/environments/production.rb +46 -0
- data/sample_app/config/environments/test.rb +32 -0
- data/sample_app/config/initializers/backtrace_silencers.rb +7 -0
- data/sample_app/config/initializers/inflections.rb +10 -0
- data/sample_app/config/initializers/mime_types.rb +5 -0
- data/sample_app/config/initializers/secret_token.rb +7 -0
- data/sample_app/config/initializers/session_store.rb +8 -0
- data/sample_app/config/locales/en.yml +5 -0
- data/sample_app/config/routes.rb +58 -0
- data/sample_app/config/shards.yml +28 -0
- data/sample_app/db/migrate/20100720172715_create_users.rb +15 -0
- data/sample_app/db/migrate/20100720172730_create_items.rb +16 -0
- data/sample_app/db/migrate/20100720210335_create_sample_users.rb +11 -0
- data/sample_app/db/schema.rb +29 -0
- data/sample_app/db/seeds.rb +16 -0
- data/sample_app/doc/README_FOR_APP +2 -0
- data/sample_app/features/migrate.feature +44 -0
- data/sample_app/features/seed.feature +15 -0
- data/sample_app/features/step_definitions/seeds_steps.rb +15 -0
- data/sample_app/features/step_definitions/web_steps.rb +219 -0
- data/sample_app/features/support/env.rb +65 -0
- data/sample_app/features/support/paths.rb +33 -0
- data/sample_app/lib/tasks/.gitkeep +0 -0
- data/sample_app/lib/tasks/cucumber.rake +53 -0
- data/sample_app/public/404.html +26 -0
- data/sample_app/public/422.html +26 -0
- data/sample_app/public/500.html +26 -0
- data/sample_app/public/favicon.ico +0 -0
- data/sample_app/public/images/rails.png +0 -0
- data/sample_app/public/index.html +279 -0
- data/sample_app/public/javascripts/application.js +2 -0
- data/sample_app/public/javascripts/controls.js +965 -0
- data/sample_app/public/javascripts/dragdrop.js +974 -0
- data/sample_app/public/javascripts/effects.js +1123 -0
- data/sample_app/public/javascripts/prototype.js +4874 -0
- data/sample_app/public/javascripts/rails.js +118 -0
- data/sample_app/public/robots.txt +5 -0
- data/sample_app/public/stylesheets/.gitkeep +0 -0
- data/sample_app/script/cucumber +10 -0
- data/sample_app/script/rails +6 -0
- data/sample_app/spec/models/item_spec.rb +5 -0
- data/sample_app/spec/models/user_spec.rb +5 -0
- data/sample_app/spec/spec_helper.rb +27 -0
- data/sample_app/test/performance/browsing_test.rb +9 -0
- data/sample_app/test/test_helper.rb +13 -0
- data/sample_app/vendor/plugins/.gitkeep +0 -0
- data/spec/config/shards.yml +16 -18
- data/spec/database_models.rb +5 -0
- data/spec/octopus/model_spec.rb +77 -14
- data/spec/octopus/proxy_spec.rb +2 -0
- data/spec/octopus/replication_specs.rb +5 -0
- metadata +72 -8
@@ -0,0 +1,118 @@
|
|
1
|
+
document.observe("dom:loaded", function() {
|
2
|
+
function handleRemote(element) {
|
3
|
+
var method, url, params;
|
4
|
+
|
5
|
+
if (element.tagName.toLowerCase() === 'form') {
|
6
|
+
method = element.readAttribute('method') || 'post';
|
7
|
+
url = element.readAttribute('action');
|
8
|
+
params = element.serialize(true);
|
9
|
+
} else {
|
10
|
+
method = element.readAttribute('data-method') || 'get';
|
11
|
+
url = element.readAttribute('href');
|
12
|
+
params = {};
|
13
|
+
}
|
14
|
+
|
15
|
+
var event = element.fire("ajax:before");
|
16
|
+
if (event.stopped) return false;
|
17
|
+
|
18
|
+
new Ajax.Request(url, {
|
19
|
+
method: method,
|
20
|
+
parameters: params,
|
21
|
+
asynchronous: true,
|
22
|
+
evalScripts: true,
|
23
|
+
|
24
|
+
onLoading: function(request) { element.fire("ajax:loading", {request: request}); },
|
25
|
+
onLoaded: function(request) { element.fire("ajax:loaded", {request: request}); },
|
26
|
+
onInteractive: function(request) { element.fire("ajax:interactive", {request: request}); },
|
27
|
+
onComplete: function(request) { element.fire("ajax:complete", {request: request}); },
|
28
|
+
onSuccess: function(request) { element.fire("ajax:success", {request: request}); },
|
29
|
+
onFailure: function(request) { element.fire("ajax:failure", {request: request}); }
|
30
|
+
});
|
31
|
+
|
32
|
+
element.fire("ajax:after");
|
33
|
+
}
|
34
|
+
|
35
|
+
function handleMethod(element) {
|
36
|
+
var method, url, token_name, token;
|
37
|
+
|
38
|
+
method = element.readAttribute('data-method');
|
39
|
+
url = element.readAttribute('href');
|
40
|
+
csrf_param = $$('meta[name=csrf-param]').first();
|
41
|
+
csrf_token = $$('meta[name=csrf-token]').first();
|
42
|
+
|
43
|
+
var form = new Element('form', { method: "POST", action: url, style: "display: none;" });
|
44
|
+
element.parentNode.appendChild(form);
|
45
|
+
|
46
|
+
if (method != 'post') {
|
47
|
+
var field = new Element('input', { type: 'hidden', name: '_method', value: method });
|
48
|
+
form.appendChild(field);
|
49
|
+
}
|
50
|
+
|
51
|
+
if (csrf_param) {
|
52
|
+
var param = csrf_param.readAttribute('content');
|
53
|
+
var token = csrf_token.readAttribute('content');
|
54
|
+
var field = new Element('input', { type: 'hidden', name: param, value: token });
|
55
|
+
form.appendChild(field);
|
56
|
+
}
|
57
|
+
|
58
|
+
form.submit();
|
59
|
+
}
|
60
|
+
|
61
|
+
$(document.body).observe("click", function(event) {
|
62
|
+
var message = event.findElement().readAttribute('data-confirm');
|
63
|
+
if (message && !confirm(message)) {
|
64
|
+
event.stop();
|
65
|
+
return false;
|
66
|
+
}
|
67
|
+
|
68
|
+
var element = event.findElement("a[data-remote]");
|
69
|
+
if (element) {
|
70
|
+
handleRemote(element);
|
71
|
+
event.stop();
|
72
|
+
return true;
|
73
|
+
}
|
74
|
+
|
75
|
+
var element = event.findElement("a[data-method]");
|
76
|
+
if (element) {
|
77
|
+
handleMethod(element);
|
78
|
+
event.stop();
|
79
|
+
return true;
|
80
|
+
}
|
81
|
+
});
|
82
|
+
|
83
|
+
// TODO: I don't think submit bubbles in IE
|
84
|
+
$(document.body).observe("submit", function(event) {
|
85
|
+
var element = event.findElement(),
|
86
|
+
message = element.readAttribute('data-confirm');
|
87
|
+
if (message && !confirm(message)) {
|
88
|
+
event.stop();
|
89
|
+
return false;
|
90
|
+
}
|
91
|
+
|
92
|
+
var inputs = element.select("input[type=submit][data-disable-with]");
|
93
|
+
inputs.each(function(input) {
|
94
|
+
input.disabled = true;
|
95
|
+
input.writeAttribute('data-original-value', input.value);
|
96
|
+
input.value = input.readAttribute('data-disable-with');
|
97
|
+
});
|
98
|
+
|
99
|
+
var element = event.findElement("form[data-remote]");
|
100
|
+
if (element) {
|
101
|
+
handleRemote(element);
|
102
|
+
event.stop();
|
103
|
+
}
|
104
|
+
});
|
105
|
+
|
106
|
+
$(document.body).observe("ajax:after", function(event) {
|
107
|
+
var element = event.findElement();
|
108
|
+
|
109
|
+
if (element.tagName.toLowerCase() === 'form') {
|
110
|
+
var inputs = element.select("input[type=submit][disabled=true][data-disable-with]");
|
111
|
+
inputs.each(function(input) {
|
112
|
+
input.value = input.readAttribute('data-original-value');
|
113
|
+
input.writeAttribute('data-original-value', null);
|
114
|
+
input.disabled = false;
|
115
|
+
});
|
116
|
+
}
|
117
|
+
});
|
118
|
+
});
|
File without changes
|
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
vendored_cucumber_bin = Dir["#{File.dirname(__FILE__)}/../vendor/{gems,plugins}/cucumber*/bin/cucumber"].first
|
4
|
+
if vendored_cucumber_bin
|
5
|
+
load File.expand_path(vendored_cucumber_bin)
|
6
|
+
else
|
7
|
+
require 'rubygems' unless ENV['NO_RUBYGEMS']
|
8
|
+
require 'cucumber'
|
9
|
+
load Cucumber::BINARY
|
10
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
|
3
|
+
|
4
|
+
APP_PATH = File.expand_path('../../config/application', __FILE__)
|
5
|
+
require File.expand_path('../../config/boot', __FILE__)
|
6
|
+
require 'rails/commands'
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# This file is copied to ~/spec when you run 'ruby script/generate rspec'
|
2
|
+
# from the project root directory.
|
3
|
+
ENV["RAILS_ENV"] ||= 'test'
|
4
|
+
require File.expand_path("../../config/environment", __FILE__)
|
5
|
+
require 'rspec/rails'
|
6
|
+
|
7
|
+
# Requires supporting files with custom matchers and macros, etc,
|
8
|
+
# in ./support/ and its subdirectories.
|
9
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
10
|
+
|
11
|
+
RSpec.configure do |config|
|
12
|
+
# == Mock Framework
|
13
|
+
#
|
14
|
+
# If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
|
15
|
+
#
|
16
|
+
# config.mock_with :mocha
|
17
|
+
# config.mock_with :flexmock
|
18
|
+
# config.mock_with :rr
|
19
|
+
config.mock_with :rspec
|
20
|
+
|
21
|
+
config.fixture_path = "#{::Rails.root}/spec/fixtures"
|
22
|
+
|
23
|
+
# If you're not using ActiveRecord, or you'd prefer not to run each of your
|
24
|
+
# examples within a transaction, comment the following line or assign false
|
25
|
+
# instead of true.
|
26
|
+
config.use_transactional_fixtures = true
|
27
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
ENV["RAILS_ENV"] = "test"
|
2
|
+
require File.expand_path('../../config/environment', __FILE__)
|
3
|
+
require 'rails/test_help'
|
4
|
+
|
5
|
+
class ActiveSupport::TestCase
|
6
|
+
# Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
|
7
|
+
#
|
8
|
+
# Note: You'll currently still have to declare fixtures explicitly in integration tests
|
9
|
+
# -- they do not yet inherit this setting
|
10
|
+
fixtures :all
|
11
|
+
|
12
|
+
# Add more helper methods to be used by all tests here...
|
13
|
+
end
|
File without changes
|
data/spec/config/shards.yml
CHANGED
@@ -109,26 +109,24 @@ octopus_rails:
|
|
109
109
|
- production
|
110
110
|
|
111
111
|
staging:
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
database: octopus_shard3
|
112
|
+
slave1:
|
113
|
+
adapter: mysql
|
114
|
+
host: localhost
|
115
|
+
database: octopus_shard2
|
116
|
+
slave2:
|
117
|
+
adapter: mysql
|
118
|
+
host: localhost
|
119
|
+
database: octopus_shard3
|
121
120
|
|
122
121
|
production:
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
database: octopus_shard5
|
122
|
+
slave3:
|
123
|
+
adapter: mysql
|
124
|
+
host: localhost
|
125
|
+
database: octopus_shard4
|
126
|
+
slave4:
|
127
|
+
adapter: mysql
|
128
|
+
host: localhost
|
129
|
+
database: octopus_shard5
|
132
130
|
|
133
131
|
|
134
132
|
|
data/spec/database_models.rb
CHANGED
data/spec/octopus/model_spec.rb
CHANGED
@@ -11,15 +11,15 @@ describe Octopus::Model do
|
|
11
11
|
User.using(:canada).count.should == 1
|
12
12
|
User.count.should == 0
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
it "should allow selecting the shard using #new" do
|
16
16
|
u = User.using(:canada).new
|
17
17
|
u.name = "Thiago"
|
18
18
|
u.save
|
19
|
-
|
19
|
+
|
20
20
|
User.using(:canada).count.should == 1
|
21
21
|
User.using(:brazil).count.should == 0
|
22
|
-
|
22
|
+
|
23
23
|
u1 = User.new
|
24
24
|
u1.name = "Joaquim"
|
25
25
|
u2 = User.using(:canada).new
|
@@ -36,12 +36,20 @@ describe Octopus::Model do
|
|
36
36
|
User.create!(:name => 'oi')
|
37
37
|
User.count.should == 1
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
|
+
it "should allow creating more than one user" do
|
41
|
+
User.using(:canada).create([{ :name => 'America User 1' }, { :name => 'America User 2' }])
|
42
|
+
User.create!(:name => "Thiago")
|
43
|
+
User.using(:canada).find_by_name("America User 1").should_not be_nil
|
44
|
+
User.using(:canada).find_by_name("America User 2").should_not be_nil
|
45
|
+
User.using(:master).find_by_name("Thiago").should_not be_nil
|
46
|
+
end
|
47
|
+
|
40
48
|
it "should work when you have a SQLite3 shard" do
|
41
49
|
u = User.using(:sqlite_shard).create!(:name => "Sqlite3")
|
42
50
|
User.using(:sqlite_shard).find_by_name("Sqlite3").should == u
|
43
51
|
end
|
44
|
-
|
52
|
+
|
45
53
|
it "should clean #current_shard from proxy when using execute" do
|
46
54
|
ActiveRecord::Base.using(:canada).connection().execute("select * from users limit 1;")
|
47
55
|
ActiveRecord::Base.connection.current_shard.should == :master
|
@@ -52,14 +60,14 @@ describe Octopus::Model do
|
|
52
60
|
User.using(:canada).using(:master).count.should == 0
|
53
61
|
User.using(:master).using(:canada).count.should == 1
|
54
62
|
end
|
55
|
-
|
63
|
+
|
56
64
|
it "should allow find inside blocks" do
|
57
65
|
@user = User.using(:brazil).create!(:name => "Thiago")
|
58
66
|
|
59
67
|
Octopus.using(:brazil) do
|
60
68
|
User.first.should == @user
|
61
69
|
end
|
62
|
-
|
70
|
+
|
63
71
|
User.using(:brazil).find_by_name("Thiago").should == @user
|
64
72
|
end
|
65
73
|
|
@@ -195,14 +203,14 @@ describe Octopus::Model do
|
|
195
203
|
@user2.update_attributes(:name => "Joaquim")
|
196
204
|
User.using(:brazil).find_by_name("Joaquim").should_not be_nil
|
197
205
|
end
|
198
|
-
|
206
|
+
|
199
207
|
it "using update_attributes inside a block" do
|
200
208
|
Octopus.using(:brazil) do
|
201
209
|
@user = User.create!(:name => "User1")
|
202
210
|
@user2 = User.find(@user.id)
|
203
211
|
@user2.update_attributes(:name => "Joaquim")
|
204
212
|
end
|
205
|
-
|
213
|
+
|
206
214
|
User.find_by_name("Joaquim").should be_nil
|
207
215
|
User.using(:brazil).find_by_name("Joaquim").should_not be_nil
|
208
216
|
end
|
@@ -213,18 +221,18 @@ describe Octopus::Model do
|
|
213
221
|
@user2.update_attributes(:name => "Joaquim")
|
214
222
|
User.using(:brazil).find_by_name("Joaquim").should_not be_nil
|
215
223
|
end
|
216
|
-
|
224
|
+
|
217
225
|
it "transaction" do
|
218
226
|
u = User.create!(:name => "Thiago")
|
219
227
|
|
220
228
|
User.using(:brazil).count.should == 0
|
221
229
|
User.using(:master).count.should == 1
|
222
|
-
|
230
|
+
|
223
231
|
User.using(:brazil).transaction do
|
224
232
|
User.find_by_name("Thiago").should be_nil
|
225
233
|
User.create!(:name => "Brazil")
|
226
234
|
end
|
227
|
-
|
235
|
+
|
228
236
|
User.using(:brazil).count.should == 1
|
229
237
|
User.using(:master).count.should == 1
|
230
238
|
end
|
@@ -246,14 +254,69 @@ describe Octopus::Model do
|
|
246
254
|
end
|
247
255
|
end
|
248
256
|
end
|
249
|
-
|
257
|
+
|
258
|
+
describe "when you have joins/include" do
|
259
|
+
before(:each) do
|
260
|
+
@client1 = Client.using(:brazil).create(:name => "Thiago")
|
261
|
+
|
262
|
+
Octopus.using(:canada) do
|
263
|
+
@client2 = Client.create(:name => "Mike")
|
264
|
+
@client3 = Client.create(:name => "Joao")
|
265
|
+
@item1 = Item.create(:client => @client2, :name => "Item 1")
|
266
|
+
@item2 = Item.create(:client => @client2, :name => "Item 2")
|
267
|
+
@item3 = Item.create(:client => @client3, :name => "Item 3")
|
268
|
+
@part1 = Part.create(:item => @item1, :name => "Part 1")
|
269
|
+
@part2 = Part.create(:item => @item1, :name => "Part 2")
|
270
|
+
@part3 = Part.create(:item => @item2, :name => "Part 3")
|
271
|
+
end
|
272
|
+
|
273
|
+
@item4 = Item.using(:brazil).create(:client => @client1, :name => "Item 4")
|
274
|
+
end
|
275
|
+
|
276
|
+
it "should work with the rails 2.x syntax" do
|
277
|
+
items = Item.using(:canada).find(:all, :joins => :client, :conditions => { :clients => { :id => @client2.id } })
|
278
|
+
items.should == [@item1, @item2]
|
279
|
+
end
|
280
|
+
|
281
|
+
it "should work using the rails 3.x syntax" do
|
282
|
+
if Octopus.rails3?
|
283
|
+
items = Item.using(:canada).joins(:client).where("clients.id = #{@client2.id}").all
|
284
|
+
items.should == [@item1, @item2]
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
it "should work for include also, rails 2.x syntax" do
|
289
|
+
items = Item.using(:canada).find(:all, :include => :client, :conditions => { :clients => { :id => @client2.id } })
|
290
|
+
items.should == [@item1, @item2]
|
291
|
+
end
|
292
|
+
|
293
|
+
it "should work for include also, rails 3.x syntax" do
|
294
|
+
if Octopus.rails3?
|
295
|
+
items = Item.using(:canada).includes(:client).where("clients.id = #{@client2.id}").all
|
296
|
+
items.should == [@item1, @item2]
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
it "should work for multiple includes, with rails 2.x syntax" do
|
301
|
+
parts = Part.using(:canada).find(:all, :include => {:item => :client}, :conditions => {:clients => { :id => @client2.id}})
|
302
|
+
parts.should == [@part1, @part2, @part3]
|
303
|
+
parts.first.item.client.should == @client2
|
304
|
+
end
|
305
|
+
|
306
|
+
it "should work for multiple join, with rails 2.x syntax" do
|
307
|
+
parts = Part.using(:canada).find(:all, :joins => {:item => :client}, :conditions => {:clients => { :id => @client2.id}})
|
308
|
+
parts.should == [@part1, @part2, @part3]
|
309
|
+
parts.first.item.client.should == @client2
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
250
313
|
describe "ActiveRecord::Base Validations" do
|
251
314
|
it "should work correctly when using validations" do
|
252
315
|
@key = Keyboard.create!(:name => "Key")
|
253
316
|
lambda { Keyboard.using(:brazil).create!(:name => "Key") }.should_not raise_error()
|
254
317
|
lambda { Keyboard.create!(:name => "Key") }.should raise_error()
|
255
318
|
end
|
256
|
-
|
319
|
+
|
257
320
|
it "should work correctly when using validations with using syntax" do
|
258
321
|
@key = Keyboard.using(:brazil).create!(:name => "Key")
|
259
322
|
lambda { Keyboard.create!(:name => "Key") }.should_not raise_error()
|
data/spec/octopus/proxy_spec.rb
CHANGED
@@ -68,6 +68,7 @@ describe Octopus::Proxy do
|
|
68
68
|
|
69
69
|
it "should initialize correctly octopus common variables for the enviroments" do
|
70
70
|
Rails.stub!(:env).and_return('staging')
|
71
|
+
Octopus.instance_variable_set(:@rails_env, nil)
|
71
72
|
Octopus.config()
|
72
73
|
|
73
74
|
proxy.instance_variable_get(:@replicated).should be_true
|
@@ -89,6 +90,7 @@ describe Octopus::Proxy do
|
|
89
90
|
after(:each) do
|
90
91
|
Object.send(:remove_const, :Rails)
|
91
92
|
Octopus.instance_variable_set(:@config, nil)
|
93
|
+
Octopus.instance_variable_set(:@rails_env, nil)
|
92
94
|
end
|
93
95
|
end
|
94
96
|
|