ar-octopus 0.4.0 → 0.5.0

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/.gitignore +11 -0
  2. data/.travis.yml +22 -0
  3. data/Appraisals +18 -0
  4. data/Gemfile +3 -12
  5. data/README.mkdn +63 -24
  6. data/Rakefile +70 -92
  7. data/ar-octopus.gemspec +25 -198
  8. data/lib/ar-octopus.rb +1 -0
  9. data/lib/octopus.rb +73 -25
  10. data/lib/octopus/association.rb +6 -5
  11. data/lib/octopus/association_collection.rb +58 -4
  12. data/lib/octopus/has_and_belongs_to_many_association.rb +4 -4
  13. data/lib/octopus/logger.rb +9 -4
  14. data/lib/octopus/migration.rb +155 -50
  15. data/lib/octopus/model.rb +98 -34
  16. data/lib/octopus/proxy.rb +124 -53
  17. data/lib/octopus/rails2/association.rb +46 -93
  18. data/lib/octopus/rails2/persistence.rb +1 -1
  19. data/lib/octopus/rails2/scope.rb +17 -0
  20. data/lib/octopus/rails3.1/singular_association.rb +34 -0
  21. data/lib/octopus/rails3.2/persistence.rb +12 -0
  22. data/lib/octopus/rails3/abstract_adapter.rb +39 -0
  23. data/lib/octopus/rails3/arel.rb +5 -5
  24. data/lib/octopus/rails3/log_subscriber.rb +22 -0
  25. data/lib/octopus/rails3/persistence.rb +10 -5
  26. data/lib/octopus/railtie.rb +13 -0
  27. data/lib/octopus/scope_proxy.rb +22 -16
  28. data/lib/octopus/version.rb +3 -0
  29. data/lib/tasks/octopus.rake +20 -0
  30. data/sample_app/Gemfile +2 -2
  31. data/sample_app/config/initializers/inflections.rb +1 -1
  32. data/sample_app/config/initializers/secret_token.rb +1 -1
  33. data/sample_app/db/migrate/20100720172730_create_items.rb +1 -1
  34. data/sample_app/db/migrate/20100720210335_create_sample_users.rb +1 -1
  35. data/sample_app/db/seeds.rb +1 -1
  36. data/sample_app/features/migrate.feature +12 -12
  37. data/sample_app/features/seed.feature +3 -3
  38. data/sample_app/features/step_definitions/web_steps.rb +5 -5
  39. data/sample_app/features/support/env.rb +8 -8
  40. data/sample_app/lib/tasks/cucumber.rake +2 -2
  41. data/sample_app/public/javascripts/effects.js +1 -1
  42. data/spec/config/shards.yml +38 -28
  43. data/spec/migrations/11_add_field_in_all_slaves.rb +1 -1
  44. data/spec/migrations/12_create_users_using_block.rb +2 -2
  45. data/spec/migrations/13_create_users_using_block_and_using.rb +2 -2
  46. data/spec/migrations/14_create_users_on_shards_of_a_group_with_versions.rb +11 -0
  47. data/spec/migrations/1_create_users_on_master.rb +1 -1
  48. data/spec/migrations/2_create_users_on_canada.rb +1 -1
  49. data/spec/migrations/3_create_users_on_both_shards.rb +1 -1
  50. data/spec/migrations/4_create_users_on_shards_of_a_group.rb +1 -1
  51. data/spec/migrations/5_create_users_on_multiples_groups.rb +1 -1
  52. data/spec/migrations/6_raise_exception_with_invalid_shard_name.rb +1 -1
  53. data/spec/migrations/7_raise_exception_with_invalid_multiple_shard_names.rb +1 -1
  54. data/spec/migrations/8_raise_exception_with_invalid_group_name.rb +1 -1
  55. data/spec/migrations/9_raise_exception_with_multiple_invalid_group_names.rb +1 -1
  56. data/spec/octopus/association_spec.rb +88 -70
  57. data/spec/octopus/log_subscriber_spec.rb +22 -0
  58. data/spec/octopus/logger_spec.rb +28 -15
  59. data/spec/octopus/migration_spec.rb +47 -43
  60. data/spec/octopus/model_spec.rb +179 -13
  61. data/spec/octopus/octopus_spec.rb +26 -4
  62. data/spec/octopus/proxy_spec.rb +61 -23
  63. data/spec/octopus/{replication_specs.rb → replication_spec.rb} +33 -26
  64. data/spec/octopus/scope_proxy_spec.rb +3 -3
  65. data/spec/octopus/sharded_spec.rb +9 -9
  66. data/spec/spec_helper.rb +10 -12
  67. data/spec/support/active_record/connection_adapters/modify_config_adapter.rb +17 -0
  68. data/spec/support/database_connection.rb +2 -0
  69. data/spec/{database_models.rb → support/database_models.rb} +27 -2
  70. data/spec/support/octopus_helper.rb +50 -0
  71. data/spec/tasks/octopus.rake_spec.rb +36 -0
  72. metadata +188 -169
  73. data/Gemfile.lock +0 -68
  74. data/lib/octopus/rails3/association.rb +0 -112
  75. data/spec/database_connection.rb +0 -4
  76. data/spec/octopus/controller_spec.rb +0 -34
  77. data/spec/octopus_helper.rb +0 -37
@@ -1,68 +0,0 @@
1
- GEM
2
- remote: http://rubygems.org/
3
- specs:
4
- abstract (1.0.0)
5
- actionpack (3.0.6)
6
- activemodel (= 3.0.6)
7
- activesupport (= 3.0.6)
8
- builder (~> 2.1.2)
9
- erubis (~> 2.6.6)
10
- i18n (~> 0.5.0)
11
- rack (~> 1.2.1)
12
- rack-mount (~> 0.6.14)
13
- rack-test (~> 0.5.7)
14
- tzinfo (~> 0.3.23)
15
- activemodel (3.0.6)
16
- activesupport (= 3.0.6)
17
- builder (~> 2.1.2)
18
- i18n (~> 0.5.0)
19
- activerecord (3.0.6)
20
- activemodel (= 3.0.6)
21
- activesupport (= 3.0.6)
22
- arel (~> 2.0.2)
23
- tzinfo (~> 0.3.23)
24
- activesupport (3.0.6)
25
- arel (2.0.9)
26
- builder (2.1.2)
27
- diff-lcs (1.1.2)
28
- erubis (2.6.6)
29
- abstract (>= 1.0.0)
30
- git (1.2.5)
31
- i18n (0.5.0)
32
- jeweler (1.5.2)
33
- bundler (~> 1.0.0)
34
- git (>= 1.2.5)
35
- rake
36
- mysql2 (0.2.6)
37
- pg (0.10.1)
38
- rack (1.2.2)
39
- rack-mount (0.6.14)
40
- rack (>= 1.0.0)
41
- rack-test (0.5.7)
42
- rack (>= 1.0)
43
- rake (0.8.7)
44
- rspec (2.5.0)
45
- rspec-core (~> 2.5.0)
46
- rspec-expectations (~> 2.5.0)
47
- rspec-mocks (~> 2.5.0)
48
- rspec-core (2.5.1)
49
- rspec-expectations (2.5.0)
50
- diff-lcs (~> 1.1.2)
51
- rspec-mocks (2.5.0)
52
- sqlite3 (1.3.3)
53
- sqlite3-ruby (1.3.3)
54
- sqlite3 (>= 1.3.3)
55
- tzinfo (0.3.26)
56
-
57
- PLATFORMS
58
- ruby
59
-
60
- DEPENDENCIES
61
- actionpack (= 3.0.6)
62
- activerecord (= 3.0.6)
63
- jeweler (>= 1.4)
64
- mysql2
65
- pg (>= 0.9.0)
66
- rake (>= 0.8.7)
67
- rspec
68
- sqlite3-ruby (>= 1.3.1)
@@ -1,112 +0,0 @@
1
- module Octopus
2
- module Rails3
3
- module Association
4
- def collection_reader_method(reflection, association_proxy_class)
5
- define_method(reflection.name) do |*params|
6
- force_reload = params.first unless params.empty?
7
- reload_connection()
8
-
9
- association = association_instance_get(reflection.name)
10
-
11
- unless association
12
- association = association_proxy_class.new(self, reflection)
13
- association_instance_set(reflection.name, association)
14
- end
15
-
16
- reflection.klass.uncached { association.reload } if force_reload
17
-
18
- association
19
- end
20
-
21
- define_method("#{reflection.name.to_s.singularize}_ids") do
22
- reload_connection()
23
- if send(reflection.name).loaded? || reflection.options[:finder_sql]
24
- send(reflection.name).map(&:id)
25
- else
26
- if reflection.through_reflection && reflection.source_reflection.belongs_to?
27
- through = reflection.through_reflection
28
- primary_key = reflection.source_reflection.primary_key_name
29
- send(through.name).select("DISTINCT #{through.quoted_table_name}.#{primary_key}").map!(&:"#{primary_key}")
30
- else
31
- send(reflection.name).select("#{reflection.quoted_table_name}.#{reflection.klass.primary_key}").except(:includes).map!(&:id)
32
- end
33
- end
34
- end
35
- end
36
-
37
- def association_constructor_method(constructor, reflection, association_proxy_class)
38
- define_method("#{constructor}_#{reflection.name}") do |*params|
39
- reload_connection()
40
- attributees = params.first unless params.empty?
41
- replace_existing = params[1].nil? ? true : params[1]
42
- association = association_instance_get(reflection.name)
43
-
44
- unless association
45
- association = association_proxy_class.new(self, reflection)
46
- association_instance_set(reflection.name, association)
47
- end
48
-
49
- if association_proxy_class == ActiveRecord::Associations::HasOneAssociation
50
- return_val = association.send(constructor, attributees, replace_existing)
51
- else
52
- return_val = association.send(constructor, attributees)
53
- end
54
-
55
- if should_set_current_shard?
56
- return_val.current_shard = self.current_shard
57
- end
58
-
59
- return_val
60
- end
61
- end
62
-
63
- def association_accessor_methods(reflection, association_proxy_class)
64
- define_method(reflection.name) do |*params|
65
- reload_connection()
66
- force_reload = params.first unless params.empty?
67
- association = association_instance_get(reflection.name)
68
-
69
- if association.nil? || force_reload
70
- association = association_proxy_class.new(self, reflection)
71
- retval = force_reload ? reflection.klass.uncached { association.reload } : association.reload
72
- if retval.nil? and association_proxy_class == ActiveRecord::Associations::BelongsToAssociation
73
- association_instance_set(reflection.name, nil)
74
- return nil
75
- end
76
- association_instance_set(reflection.name, association)
77
- end
78
-
79
- association.target.nil? ? nil : association
80
- end
81
-
82
- define_method("loaded_#{reflection.name}?") do
83
- reload_connection()
84
- association = association_instance_get(reflection.name)
85
- association && association.loaded?
86
- end
87
-
88
- define_method("#{reflection.name}=") do |new_value|
89
- reload_connection()
90
- association = association_instance_get(reflection.name)
91
-
92
- if association.nil? || association.target != new_value
93
- association = association_proxy_class.new(self, reflection)
94
- end
95
-
96
- association.replace(new_value)
97
- association_instance_set(reflection.name, new_value.nil? ? nil : association)
98
- end
99
-
100
- define_method("set_#{reflection.name}_target") do |target|
101
- return if target.nil? and association_proxy_class == ActiveRecord::Associations::BelongsToAssociation
102
- reload_connection()
103
- association = association_proxy_class.new(self, reflection)
104
- association.target = target
105
- association_instance_set(reflection.name, association)
106
- end
107
- end
108
- end
109
- end
110
- end
111
-
112
- ActiveRecord::Base.extend(Octopus::Rails3::Association)
@@ -1,4 +0,0 @@
1
- require 'rubygems'
2
- require 'active_record'
3
-
4
- ActiveRecord::Base.establish_connection(:adapter => "mysql2", :database => "octopus_shard1", :username => "root", :password => "")
@@ -1,34 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
-
3
- describe "Rails Controllers" do
4
- it "should use #using method to in all requests" do
5
- class UsersControllers < ActionController::Base
6
- around_filter :select_shard
7
- def create
8
- User.create!(:name => "ActionController")
9
- render :nothing => true
10
- end
11
-
12
- def select_shard(&block)
13
- Octopus.using(:brazil, &block)
14
- end
15
-
16
- def self._routes
17
- ActionDispatch::Routing::RouteSet.new
18
- end
19
- end
20
-
21
- UsersControllers.action_methods.include?("create").should be_true
22
-
23
- if Octopus.rails3?
24
- a = UsersControllers.new
25
- a.stub!(:request).and_return(mock({:fullpath => "", :filtered_parameters => {}, :formats => [mock(:to_sym => :xml, :ref => "xml")], :method => "GET"}))
26
- a.instance_variable_set(:@_response, mock(:content_type => "xml", :body= => "", :status => 401))
27
- a.process(:create)
28
- User.using(:brazil).find_by_name("ActionController").should_not be_nil
29
- User.using(:master).find_by_name("ActionController").should be_nil
30
- else
31
- pending()
32
- end
33
- end
34
- end
@@ -1,37 +0,0 @@
1
- def clean_all_shards()
2
- @@shards ||= ActiveRecord::Base.using(:master).connection.instance_variable_get(:@shards).keys
3
- @@shards.each do |shard_symbol|
4
- ['schema_migrations', 'users', 'clients', 'cats', 'items', 'keyboards', 'computers', 'permissions_roles', 'roles', 'permissions', 'assignments', 'projects', 'programmers', "yummy"].each do |tables|
5
- ActiveRecord::Base.using(shard_symbol).connection.execute("DELETE FROM #{tables}")
6
- end
7
- end
8
- end
9
-
10
- def clean_connection_proxy()
11
- Thread.current[:connection_proxy] = nil
12
- end
13
-
14
- def migrating_to_version(version, &block)
15
- begin
16
- ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT, version)
17
- yield
18
- ensure
19
- ActiveRecord::Migrator.run(:down, MIGRATIONS_ROOT, version)
20
- end
21
- end
22
-
23
- def using_environment(environment, &block)
24
- begin
25
- set_octopus_env(environment.to_s)
26
- clean_connection_proxy()
27
- yield
28
- ensure
29
- set_octopus_env('octopus')
30
- clean_connection_proxy()
31
- end
32
- end
33
-
34
- def set_octopus_env(env)
35
- Octopus.instance_variable_set(:@config, nil)
36
- Octopus.stub!(:env).and_return(env)
37
- end