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.
Files changed (77) hide show
  1. data/Rakefile +9 -2
  2. data/ar-octopus.gemspec +70 -5
  3. data/lib/octopus/has_and_belongs_to_many_association.rb +1 -5
  4. data/lib/octopus/model.rb +6 -16
  5. data/lib/octopus/proxy.rb +1 -6
  6. data/lib/octopus/scope_proxy.rb +7 -10
  7. data/sample_app/.gitignore +4 -0
  8. data/sample_app/.rspec +1 -0
  9. data/sample_app/Gemfile +22 -0
  10. data/sample_app/Gemfile.lock +149 -0
  11. data/sample_app/README +3 -0
  12. data/sample_app/Rakefile +7 -0
  13. data/sample_app/app/controllers/application_controller.rb +4 -0
  14. data/sample_app/app/helpers/application_helper.rb +2 -0
  15. data/sample_app/app/models/item.rb +2 -0
  16. data/sample_app/app/models/user.rb +2 -0
  17. data/sample_app/app/views/layouts/application.html.erb +14 -0
  18. data/sample_app/autotest/discover.rb +2 -0
  19. data/sample_app/config.ru +4 -0
  20. data/sample_app/config/application.rb +46 -0
  21. data/sample_app/config/boot.rb +13 -0
  22. data/sample_app/config/cucumber.yml +8 -0
  23. data/sample_app/config/database.yml +25 -0
  24. data/sample_app/config/environment.rb +5 -0
  25. data/sample_app/config/environments/development.rb +19 -0
  26. data/sample_app/config/environments/production.rb +46 -0
  27. data/sample_app/config/environments/test.rb +32 -0
  28. data/sample_app/config/initializers/backtrace_silencers.rb +7 -0
  29. data/sample_app/config/initializers/inflections.rb +10 -0
  30. data/sample_app/config/initializers/mime_types.rb +5 -0
  31. data/sample_app/config/initializers/secret_token.rb +7 -0
  32. data/sample_app/config/initializers/session_store.rb +8 -0
  33. data/sample_app/config/locales/en.yml +5 -0
  34. data/sample_app/config/routes.rb +58 -0
  35. data/sample_app/config/shards.yml +28 -0
  36. data/sample_app/db/migrate/20100720172715_create_users.rb +15 -0
  37. data/sample_app/db/migrate/20100720172730_create_items.rb +16 -0
  38. data/sample_app/db/migrate/20100720210335_create_sample_users.rb +11 -0
  39. data/sample_app/db/schema.rb +29 -0
  40. data/sample_app/db/seeds.rb +16 -0
  41. data/sample_app/doc/README_FOR_APP +2 -0
  42. data/sample_app/features/migrate.feature +44 -0
  43. data/sample_app/features/seed.feature +15 -0
  44. data/sample_app/features/step_definitions/seeds_steps.rb +15 -0
  45. data/sample_app/features/step_definitions/web_steps.rb +219 -0
  46. data/sample_app/features/support/env.rb +65 -0
  47. data/sample_app/features/support/paths.rb +33 -0
  48. data/sample_app/lib/tasks/.gitkeep +0 -0
  49. data/sample_app/lib/tasks/cucumber.rake +53 -0
  50. data/sample_app/public/404.html +26 -0
  51. data/sample_app/public/422.html +26 -0
  52. data/sample_app/public/500.html +26 -0
  53. data/sample_app/public/favicon.ico +0 -0
  54. data/sample_app/public/images/rails.png +0 -0
  55. data/sample_app/public/index.html +279 -0
  56. data/sample_app/public/javascripts/application.js +2 -0
  57. data/sample_app/public/javascripts/controls.js +965 -0
  58. data/sample_app/public/javascripts/dragdrop.js +974 -0
  59. data/sample_app/public/javascripts/effects.js +1123 -0
  60. data/sample_app/public/javascripts/prototype.js +4874 -0
  61. data/sample_app/public/javascripts/rails.js +118 -0
  62. data/sample_app/public/robots.txt +5 -0
  63. data/sample_app/public/stylesheets/.gitkeep +0 -0
  64. data/sample_app/script/cucumber +10 -0
  65. data/sample_app/script/rails +6 -0
  66. data/sample_app/spec/models/item_spec.rb +5 -0
  67. data/sample_app/spec/models/user_spec.rb +5 -0
  68. data/sample_app/spec/spec_helper.rb +27 -0
  69. data/sample_app/test/performance/browsing_test.rb +9 -0
  70. data/sample_app/test/test_helper.rb +13 -0
  71. data/sample_app/vendor/plugins/.gitkeep +0 -0
  72. data/spec/config/shards.yml +16 -18
  73. data/spec/database_models.rb +5 -0
  74. data/spec/octopus/model_spec.rb +77 -14
  75. data/spec/octopus/proxy_spec.rb +2 -0
  76. data/spec/octopus/replication_specs.rb +5 -0
  77. 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
+ });
@@ -0,0 +1,5 @@
1
+ # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
2
+ #
3
+ # To ban all spiders from the entire site uncomment the next two lines:
4
+ # User-Agent: *
5
+ # Disallow: /
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,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe Item do
4
+ pending "add some examples to (or delete) #{__FILE__}"
5
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe User do
4
+ pending "add some examples to (or delete) #{__FILE__}"
5
+ end
@@ -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,9 @@
1
+ require 'test_helper'
2
+ require 'rails/performance_test_help'
3
+
4
+ # Profiling results for each test method are written to tmp/performance.
5
+ class BrowsingTest < ActionDispatch::PerformanceTest
6
+ def test_homepage
7
+ get '/'
8
+ end
9
+ 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
@@ -109,26 +109,24 @@ octopus_rails:
109
109
  - production
110
110
 
111
111
  staging:
112
- shards:
113
- slave1:
114
- adapter: mysql
115
- host: localhost
116
- database: octopus_shard2
117
- slave2:
118
- adapter: mysql
119
- host: localhost
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
- shards:
124
- slave3:
125
- adapter: mysql
126
- host: localhost
127
- database: octopus_shard4
128
- slave4:
129
- adapter: mysql
130
- host: localhost
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
 
@@ -21,6 +21,11 @@ end
21
21
  #This items belongs to a client
22
22
  class Item < ActiveRecord::Base
23
23
  belongs_to :client
24
+ has_many :parts
25
+ end
26
+
27
+ class Part < ActiveRecord::Base
28
+ belongs_to :item
24
29
  end
25
30
 
26
31
  class Keyboard < ActiveRecord::Base
@@ -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()
@@ -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