ar-octopus 0.0.26 → 0.0.27

Sign up to get free protection for your applications and to get access to all the features.
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