connection_manager 0.2.6 → 0.3.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 (38) hide show
  1. data/.gitignore +2 -1
  2. data/Gemfile +0 -1
  3. data/LICENSE.txt +1 -1
  4. data/README.md +115 -55
  5. data/Rakefile +2 -0
  6. data/connection_manager.gemspec +9 -3
  7. data/lib/connection_manager/connection_builder.rb +81 -0
  8. data/lib/connection_manager/connection_manager_railtie.rb +4 -3
  9. data/lib/connection_manager/helpers/abstract_adapter_helper.rb +40 -0
  10. data/lib/connection_manager/helpers/connection_helpers.rb +105 -0
  11. data/lib/connection_manager/{cross_schema_patch.rb → patches/cross_schema_patch.rb} +2 -3
  12. data/lib/connection_manager/replication.rb +165 -0
  13. data/lib/connection_manager/shards.rb +25 -0
  14. data/lib/connection_manager/using.rb +95 -0
  15. data/lib/connection_manager/version.rb +1 -1
  16. data/lib/connection_manager.rb +19 -8
  17. data/spec/factories.rb +7 -11
  18. data/spec/helpers/database_spec_helper.rb +52 -41
  19. data/spec/helpers/models_spec_helper.rb +23 -0
  20. data/spec/jdbcmysql_database.yml +55 -0
  21. data/spec/lib/connection_builder_spec.rb +29 -0
  22. data/spec/lib/connection_helpers_spec.rb +74 -0
  23. data/spec/lib/replication_spec.rb +134 -0
  24. data/spec/lib/shards_spec.rb +40 -0
  25. data/spec/lib/using_spec.rb +77 -0
  26. data/spec/mysql2_database.yml +28 -2
  27. data/spec/spec_helper.rb +20 -6
  28. metadata +42 -39
  29. data/Gemfile.lock +0 -56
  30. data/lib/connection_manager/associations.rb +0 -28
  31. data/lib/connection_manager/connections.rb +0 -124
  32. data/lib/connection_manager/method_recorder.rb +0 -57
  33. data/lib/connection_manager/secondary_connection_builder.rb +0 -180
  34. data/spec/integration/secondary_connection_builder_spec.rb +0 -115
  35. data/spec/lib/associations_spec.rb +0 -30
  36. data/spec/lib/connections_spec.rb +0 -92
  37. data/spec/lib/method_recorder_spec.rb +0 -43
  38. data/spec/lib/secondary_connection_builder_spec.rb +0 -77
@@ -1,124 +0,0 @@
1
- module ConnectionManager
2
- class Connections
3
- class << self
4
- @connection_keys
5
- @all
6
- @secondary_connections
7
- @env
8
-
9
- def env
10
- @env ||= fetch_env
11
- @env
12
- end
13
-
14
- def env=env
15
- @env = env
16
- end
17
-
18
- def env_regex(with_underscore=true)
19
- s = "#{env}$"
20
- s.insert(0,"\_") if with_underscore
21
- Regexp.new("(#{s})")
22
- end
23
-
24
- # Get the current environment if defined
25
- # Check for Rails, check for RACK_ENV, default to 'development'
26
- def fetch_env
27
- return Rails.env if defined?(Rails)
28
- return RACK_ENV if defined?(RACK_ENV)
29
- "development"
30
- end
31
-
32
- # Grab only thoses connections that correspond to the current env. If env
33
- # is blank it grabs all the connection keys
34
- def connection_keys
35
- @connection_keys ||= ActiveRecord::Base.configurations.keys.
36
- select{|n| n.match(env_regex(false))}
37
- end
38
-
39
- # Contains all the connection classes built
40
- def all
41
- @all ||= []
42
- end
43
-
44
- # Holds connections
45
- def secondary_connections
46
- @secondary_connections ||= {}
47
- end
48
-
49
- # Returns the database value given a connection key from the database.yml
50
- def database_name_from_yml(name_from_yml)
51
- clean_db_name(ActiveRecord::Base.configurations[name_from_yml]['database'])
52
- end
53
-
54
- def clean_sqlite_db_name(name,remove_env=true)
55
- new_name = "#{name}".gsub(/(\.sqlite3$)/,'')
56
- new_name = new_name.split("/").last
57
- new_name.gsub!(env_regex,'') if remove_env
58
- new_name
59
- end
60
-
61
- def clean_db_name(name)
62
- new_name = "#{name}".gsub(env_regex(false),'')
63
- if new_name.blank?
64
- new_name = "#{database_name_from_yml(name)}"
65
- end
66
- new_name = clean_sqlite_db_name(new_name)
67
- new_name.gsub(/\_$/,'')
68
- end
69
-
70
- # Given an connection key name from the database.yml, returns the string
71
- # equivelent of the class name for that entry.
72
- def connection_class_name(name_from_yml)
73
- new_class_name = clean_db_name(name_from_yml)
74
- new_class_name = new_class_name.gsub(/\_/,' ').titleize.gsub(/ /,'')
75
- new_class_name << "Connection"
76
- new_class_name
77
- end
78
-
79
- def secondary_key(name_from_yml)
80
- rep_name = clean_db_name(name_from_yml)
81
- rep_name.gsub!(/(\_)+(\d+)/,'')
82
- rep_name.to_sym
83
- end
84
-
85
- def add_secondary_connection(name_from_yml,new_connection)
86
- key = secondary_key(name_from_yml)
87
- secondary_connections[key] ||= []
88
- secondary_connections[key] << new_connection
89
- secondary_connections
90
- end
91
-
92
- def available_secondary_connections(rep_collection_key)
93
- secondary_connections[(rep_collection_key.gsub(env_regex,'')).to_sym]
94
- end
95
-
96
- # Sets class instance attributes, then builds connection classes, while populating
97
- # available_connctions and replication_connection
98
- def initialize(options={})
99
- options.each do |k,v|
100
- send("#{k.to_s}=",v)
101
- end
102
- connection_keys.each do |connection|
103
- new_connection = connection_class_name(connection)
104
- add_secondary_connection(connection,new_connection)
105
- build_connection_class(new_connection,connection)
106
- end
107
- all
108
- end
109
-
110
- # Addes a conneciton subclass to Connections using the supplied
111
- # class name and connection key from database.yml
112
- def build_connection_class(class_name,connection_key)
113
- klass = Class.new(ActiveRecord::Base) do
114
- self.abstract_class = true
115
- end
116
- new_connection_class = Object.const_set(class_name, klass)
117
- new_connection_class.table_name_prefix=("#{ActiveRecord::Base.configurations[connection_key]['database']}.")
118
- new_connection_class.establish_connection(connection_key)
119
- (const_set class_name, new_connection_class)
120
- all << class_name
121
- end
122
- end
123
- end
124
- end
@@ -1,57 +0,0 @@
1
- require 'active_record'
2
- module ConnectionManager
3
- class MethodRecorder
4
- attr_accessor :classes_to_call
5
-
6
- def initialize(classes_to_call=[])
7
- self.classes_to_call = classes_to_call
8
- end
9
-
10
- # A place to store our methods and thier variables
11
- def recordings
12
- @recordings ||= {}
13
- end
14
-
15
- def execute_recordings
16
- results = []
17
- classes_to_call.each do |class_to_call|
18
- called = nil
19
- recordings.each do |name,args|
20
- args = args[0] if [Array, Hash].include?args[0].class
21
- if called.nil?
22
- if args.blank?
23
- called = class_to_call.send(name.to_sym)
24
- else
25
- called = class_to_call.send(name.to_sym, args)
26
- end
27
- else
28
- if args.blank?
29
- called = called.send(name.to_sym)
30
- else
31
- called = called.send(name.to_sym, args)
32
- end
33
- end
34
- end
35
- if called.is_a?(Array)
36
- results = (results | called)
37
- else
38
- results << called
39
- end
40
- end
41
- results
42
- end
43
-
44
- # Create recorder classes for methods that might be called on a ActiveRecord
45
- # model in the process of building a query
46
- (ActiveRecord::FinderMethods.instance_methods | ActiveRecord::QueryMethods.instance_methods).each do |method|
47
- define_method(method) do |*args|
48
- recordings[method] = args
49
- self
50
- end
51
- end
52
-
53
- def execute
54
- execute_recordings
55
- end
56
- end
57
- end
@@ -1,180 +0,0 @@
1
- module ConnectionManager
2
- module SecondaryConnectionBuilder
3
-
4
- def database_name
5
- "#{connection.instance_variable_get(:@config)[:database].to_s}"
6
- end
7
-
8
- def secondary_association_options(method,association,class_name,options={})
9
- new_options = {}.merge(options)
10
- if new_options[:class_name].blank?
11
- new_options[:class_name] = "#{association.to_s.singularize.classify}::#{class_name}"
12
- else
13
- new_options[:class_name] = "#{new_options[:class_name]}::#{class_name}"
14
- end
15
-
16
- if [:has_one,:has_many].include?(method) && new_options[:foreign_key].blank?
17
- new_options[:foreign_key] = "#{table_name.singularize}_id"
18
- end
19
- new_options
20
- end
21
-
22
- def build_secondary_associations(class_name)
23
- str = ""
24
- defined_associations.each do |method,defs|
25
- unless defs.blank?
26
- defs.each do |association,options|
27
- options = {} if options.blank?
28
- unless options[:no_readonly] || options[:class_name].to_s.match("::#{class_name}")
29
- str << "#{method.to_s} :#{association}, #{secondary_association_options(method,association,class_name,options)};"
30
- end
31
- end
32
- end
33
- end
34
- str
35
- end
36
-
37
- def secondary_connection_classes(options)
38
- if options[:using] && options[:using].is_a?(Array)
39
- connection_classes = options[:using].collect{|c| Connections.connection_class_name(c)}
40
- else
41
- rep_name = "#{options[:name].to_s}_#{Connections.clean_sqlite_db_name(database_name)}"
42
- connection_classes = Connections.available_secondary_connections(rep_name)
43
- end
44
- connection_classes
45
- end
46
-
47
- def replicated(*settings)
48
- options = {:name => "slave", :readonly => true, :replication => true}.merge(settings.extract_options!)
49
- build_secondary_connections(options)
50
- end
51
-
52
- def shard(*settings)
53
- options = {:name => "shard", :readonly => false, :shards => true}.merge(settings.extract_options!)
54
- build_secondary_connections(options)
55
- end
56
-
57
- def child_connection_class?
58
- false
59
- end
60
- # Adds subclass with the class name of the type provided in the options, which
61
- # defaults to 'slave' if blank, that uses the connection from a connection class.
62
- # If :database option is blank?, replicated will assume the database.yml has
63
- # slave connections defined as: slave_database_name_test or slave_1_database_name_test,
64
- # where slave_1 is the secondary instance, 'database_name' is the actual
65
- # name of the database and '_test' is the Rails environment
66
- def build_secondary_connections(options={})
67
- unless name.match(/\:\:/)
68
- connection_classes = secondary_connection_classes(options)
69
- sub_classes = []
70
- if connection_classes.blank?
71
- raise ArgumentError, " a secondary connection was not found. Check your database.yml."
72
- else
73
- connection_methods = []
74
- connection_classes.each do |c|
75
- under_scored = c.underscore
76
- method_name = under_scored.split("_")[0]
77
- method_name = method_name.insert(method_name.index(/\d/),"_")
78
- class_name = method_name.classify
79
- connection_methods << method_name.to_sym
80
- # set_table_name_for_joins
81
- build_secondary_class(class_name,c,options)
82
- build_single_secondary_method(method_name,class_name)
83
- sub_classes << "#{self.name}::#{class_name}".constantize if options[:shards]
84
- end
85
- end
86
- build_slaves_method(connection_methods) if options[:replication]
87
- build_shards_method(sub_classes) if options[:shards]
88
- end
89
- end
90
-
91
- # Creats a subclass that inherets from the model. The default model_name
92
- # class method is overriden to return the super's name, which ensures rails
93
- # helpers like link_to called on a secondary stance generate a url for the
94
- # master database. If options include readonly, build_secondary_class also
95
- # overrides the rails "readonly?" method to ensure saves are prevented.
96
- # secondary class can be called directly for operaitons.
97
- # Usage:
98
- # User::Slave1.where(:id => 1).first => returns results from slave_1 database
99
- # User::Slave2.where(:id => 2).first => returns results from slave_2 database
100
- # User::Shard1.where(:id => 2).first => returns results from slave_1 database
101
- def build_secondary_class(class_name,connection_name,options)
102
- klass = Class.new(self) do
103
- class << self
104
- def model_name
105
- ActiveModel::Name.new(superclass)
106
- end
107
- def child_connection_class?
108
- true
109
- end
110
- end
111
-
112
- if (options[:name] == "readonly" || options[:readonly])
113
- def readonly?
114
- true
115
- end
116
- end
117
- end
118
-
119
- sub_class = const_set(class_name, klass)
120
- sub_class.build_secondary_associations(class_name)
121
- sub_class.class_eval <<-STR, __FILE__, __LINE__
122
- class << self
123
- def connection
124
- Connections::#{connection_name}.connection
125
- end
126
- end
127
- STR
128
- connection_sub_classes << sub_class
129
- sub_class
130
- end
131
-
132
- def connection_sub_classes
133
- @connection_sub_classes ||= []
134
- end
135
-
136
- def set_table_name_for_joins
137
- self.table_name_prefix = "#{database_name}." unless database_name.match(/\.sqlite3$/)
138
- end
139
-
140
- # Adds as class method to call a specific secondary conneciton.
141
- # Usage:
142
- # User.slave_1.where(:id => 2).first => returns results from slave_1 database
143
- # User.slave_2.where(:id => 2).first => returns results from slave_2 database
144
- def build_single_secondary_method(method_name,class_name)
145
- self.class.instance_eval do
146
- define_method method_name.to_s do
147
- "#{name}::#{class_name}".constantize
148
- end
149
- end
150
- end
151
-
152
- # add a class method that shifts through available connections methods
153
- # on each call.
154
- # Usage:
155
- # User.slave.where(:id => 2).first => can return results from slave_1 or slave_2
156
- def build_slaves_method(connection_methods)
157
- @connection_methods = connection_methods
158
- self.class.instance_eval do
159
- define_method 'slaves' do
160
- current = @connection_methods.shift
161
- @connection_methods << current
162
- send(current)
163
- end
164
- alias_method :slave, :slaves
165
- end
166
- end
167
-
168
- # add a class method that shifts through available connections methods
169
- # on each call.
170
- # Usage:
171
- # User.shards.where(:id => 2).first => can return results from slave_1 or slave_2
172
- def build_shards_method(connection_classes)
173
- self.class.instance_eval do
174
- define_method 'shards' do
175
- ConnectionManager::MethodRecorder.new(connection_classes)
176
- end
177
- end
178
- end
179
- end
180
- end
@@ -1,115 +0,0 @@
1
- require 'spec_helper'
2
-
3
- # Tests for associations build form replication.
4
-
5
- describe ConnectionManager::SecondaryConnectionBuilder do
6
- before(:all) do
7
- # Make sure connections recreated in other tests do not presist to current
8
- ConnectionManager::Connections.all.clear
9
- ConnectionManager::Connections.secondary_connections.clear
10
-
11
- #Initialize
12
- ConnectionManager::Connections.initialize(:env => 'test')
13
-
14
- # Add Replication to models
15
- Fruit.replicated
16
- Basket.replicated
17
- FruitBasket.replicated
18
- Region.replicated :readonly => false
19
- end
20
-
21
- context "models that have been replicated" do
22
- it "should respond to slave_1" do
23
- Fruit.respond_to?(:slave_1).should be_true
24
- end
25
-
26
- it "should respond to slave" do
27
- Fruit.respond_to?(:slave).should be_true
28
- end
29
-
30
- it "should have a subclass of Slave1" do
31
- defined?(Fruit::Slave1).should be_true
32
- end
33
-
34
- context "subclasses" do
35
- it "should have a superclass of the parent class" do
36
-
37
- Fruit::Slave1.superclass.should eql(Fruit)
38
- end
39
- end
40
- end
41
-
42
- context "readonly" do
43
- end
44
-
45
- context "slave" do
46
- context('belongs_to') do
47
- it "should return the same belongs to object as master" do
48
- fruit = Factory.create(:fruit)
49
- slave_fruit = Fruit.slave.where(:id => fruit.id).first
50
- slave_fruit.region.id.should eql(fruit.region.id)
51
- end
52
- end
53
-
54
- context('has_one') do
55
- it "should return the same has_on object as master" do
56
- region = Factory.create(:fruit).region
57
- slave_region = Region.slave.where(:id => region.id).first
58
- slave_region.fruit.id.should eql(region.fruit.id)
59
- end
60
- end
61
-
62
- context('has_many') do
63
- it "should return the same has_many objects as master" do
64
- fruit = Factory.create(:fruit)
65
- 3.times do
66
- Factory.create(:fruit_basket, :fruit_id => fruit.id)
67
- end
68
- fruit.fruit_baskets.length.should eql(3)
69
- slave_fruit = Fruit.slave.where(:id => fruit.id).first
70
- slave_fruit.fruit_baskets.length.should eql(fruit.fruit_baskets.length)
71
- slave_fruit.fruit_baskets.collect(&:id).should eql(fruit.fruit_baskets.collect(&:id))
72
- end
73
- end
74
-
75
- context('has_many :through') do
76
- it "should return the same fruit as master" do
77
- basket = Factory.create(:fruit_basket)
78
- slave_fruit = Fruit.slave.where(:id => basket.fruit_id).first
79
- master_fruit = Fruit.where(:id => basket.fruit_id).first
80
- slave_fruit.basket_ids.should eql(master_fruit.basket_ids)
81
- end
82
- end
83
- context "readonly" do
84
- it "should return a readonly object by default" do
85
- Factory.create(:fruit)
86
- readonly_fruit = Fruit.slave.first
87
- readonly_fruit.readonly?.should be_true
88
- lambda { readonly_fruit.save }.should raise_error
89
- end
90
- it "should not return readonly if replicated readonly is to false" do
91
- Factory.create(:region)
92
- Region.slave.first.readonly?.should be_false
93
- end
94
- end
95
- end
96
- context "model_name for slave" do
97
- it "should return the supers model_name" do
98
- Fruit.slave_1.model_name.should eql(Fruit.model_name)
99
- end
100
-
101
- it "should not interfear with inheritance" do
102
- Factory.create(:fruit)
103
- class MyFruit < Fruit
104
- replicated
105
- end
106
- Fruit.model_name.should_not eql(MyFruit.model_name)
107
- MyFruit.model_name.should eql("MyFruit")
108
- MyFruit.model_name.respond_to?(:plural).should be_true
109
- MyFruit.slave_1.model_name.should eql("MyFruit")
110
- MyFruit.slave_1.first.class.should eql(MyFruit::Slave1)
111
-
112
- end
113
- end
114
- end
115
-
@@ -1,30 +0,0 @@
1
- require 'spec_helper'
2
- class Foo < ActiveRecord::Base
3
- belongs_to :that
4
- has_many :foo_bars
5
- has_many :bars, :through => :foo_bars
6
- has_one :noob
7
- end
8
-
9
- class Bar < ActiveRecord::Base
10
- has_many :foo_bars
11
- has_many :foos, :through => :foo_bars
12
- end
13
-
14
- describe ConnectionManager::Associations do
15
-
16
- it "should add associations as keys to @defined_associations" do
17
- Foo.defined_associations.keys.should eql([:belongs_to,:has_many,:has_one])
18
- Bar.defined_associations.keys.should eql([:has_many])
19
- end
20
-
21
- context "defined_association values" do
22
- it "should be an array of association options (which are Arrays as well)" do
23
- Foo.defined_associations[:belongs_to].should eql([[:that]])
24
- Foo.defined_associations[:has_many].should eql([[:foo_bars],[:bars, {:through=>:foo_bars, :extend=>[]}]]) # when options are present active_record addes the :extend option defaulted to []
25
- Foo.defined_associations[:has_one].should eql([[:noob]])
26
- end
27
- end
28
-
29
- end
30
-
@@ -1,92 +0,0 @@
1
- require 'spec_helper'
2
- describe ConnectionManager::Connections do
3
- # For all tests set the env to "test"
4
- before(:all) do
5
- ConnectionManager::Connections.env = "test"
6
- end
7
- context '#clean_sqlite_db_name' do
8
- it "should remove the directory .sqlite3, Rails.env from the string" do
9
- ConnectionManager::Connections.clean_sqlite_db_name("db/my_database_test.sqlite3").should eql("my_database")
10
- end
11
- end
12
-
13
- context '#clean_db_name' do
14
- context "when name is not just the Rails.env" do
15
- it "should remove the Rails.env from the string" do
16
- ConnectionManager::Connections.clean_db_name("my_database_test").should eql("my_database")
17
- end
18
- end
19
- context "when the name is only the Rails.env" do
20
- it "should use the name of the database and remove the Rails.env" do
21
- ConnectionManager::Connections.stubs(:database_name_from_yml).returns("my_database_test")
22
- ConnectionManager::Connections.clean_db_name("test").should eql("my_database")
23
- end
24
- it "should account for sqlite3 database name" do
25
- ConnectionManager::Connections.stubs(:database_name_from_yml).returns("db/my_database_test.sqlite3")
26
- ConnectionManager::Connections.clean_db_name("test").should eql("my_database")
27
- end
28
- end
29
- end
30
-
31
- context '#connection_class_name' do
32
-
33
- it "should return a string for a class name appended with 'Connection' " do
34
- ConnectionManager::Connections.connection_class_name("my_database").should eql("MyDatabaseConnection")
35
- end
36
- it "should return remove the appended rails env" do
37
- ConnectionManager::Connections.connection_class_name("my_database_test").should eql("MyDatabaseConnection")
38
- end
39
- it "should handle sqlite database names correctly " do
40
- ConnectionManager::Connections.connection_class_name("db/my_database_test.sqlite3").should eql("MyDatabaseConnection")
41
- end
42
- it "should use the database name from the database.yml if supplied string is only is only the Rails.env" do
43
- ConnectionManager::Connections.stubs(:database_name_from_yml).returns("my_test_test")
44
- ConnectionManager::Connections.connection_class_name("test").should eql("MyTestConnection")
45
- end
46
- end
47
-
48
-
49
- context 'after #initialize' do
50
- before(:all) do
51
- # Make sure connections recreated in other tests do not presist to tests tests
52
- ConnectionManager::Connections.all.clear
53
- ConnectionManager::Connections.secondary_connections.clear
54
-
55
- #Initialize
56
- ConnectionManager::Connections.initialize(:env => 'test')
57
- end
58
-
59
- context '#all' do
60
- it "should return the database.yml entries for the current rails environment" do
61
- ConnectionManager::Connections.all.should eql(["CmConnection",
62
- "Slave1CmConnection", "Slave2CmConnection", "Shard1CmConnection"])
63
- end
64
- end
65
-
66
- context '#secondary_connections' do
67
- it "should return a hash where the keys are the generic undescored names for all connections" do
68
- ConnectionManager::Connections.secondary_connections.keys.
69
- should eql([:cm, :slave_cm, :shard_cm])
70
- end
71
- it "should return a hash where the values are an array of connection class names as strings" do
72
- first_value = ConnectionManager::Connections.secondary_connections.values.first
73
- first_value.class.should eql(Array)
74
- defined?((ConnectionManager::Connections.class_eval(first_value[0]))).should be_true
75
- end
76
- end
77
-
78
- context '#build_connection_class' do
79
- before(:all) do
80
- ConnectionManager::Connections.build_connection_class("MyConnectionClass", 'test')
81
- end
82
- it "should add a class with supplied class name to ConnectionManager::Connections" do
83
- defined?(ConnectionManager::Connections::MyConnectionClass).should be_true
84
- ConnectionManager::Connections::MyConnectionClass.is_a?(Class).should be_true
85
- end
86
- it "should have a super class of ActiveRecord::Base" do
87
- ConnectionManager::Connections::MyConnectionClass.superclass.should eql(ActiveRecord::Base)
88
- end
89
- end
90
- end
91
- end
92
-
@@ -1,43 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe ConnectionManager::MethodRecorder do
4
- before(:all) do
5
- TestMigrations.up('shard_1_cm_test')
6
- ConnectionManager::Connections.initialize(:env => 'test')
7
- class Fruit < ActiveRecord::Base
8
- shard(:using => ["shard_1_cm_test"])
9
- end
10
-
11
- end
12
- context 'shards'do
13
- it "it should record methods" do
14
- a = Fruit.shards.select('fruits.*').where(:id => 1).order('created_at').first
15
- a.recordings.should eql({:select => ['fruits.*'], :where => [:id =>1], :order => ['created_at'], :first => []})
16
- end
17
-
18
- context '#execute' do
19
- it "should return an array of results" do
20
- a = Fruit.shards.first.execute
21
- a.should be_a_kind_of(Array)
22
- end
23
- it "should execute the active record methods on the the provided class" do
24
- fruit = Factory.create(:fruit)
25
- class_to_call = Fruit
26
- a = class_to_call.shards.where(:id => fruit.id).first.execute
27
- a[0].should be_a_kind_of(class_to_call)
28
- end
29
-
30
- it "should not matter how the where statement is formated" do
31
- fruit = Factory.create(:fruit)
32
- a = Fruit.shards.where(:id => fruit.id).first.execute
33
- b = Fruit.shards.where(['id = ?', fruit.id]).first.execute
34
- c = Fruit.shards.where('id = ?', fruit.id).first.execute
35
- (a == b && b == c).should be_true
36
- end
37
- end
38
- end
39
- after(:all) do
40
- TestMigrations.down('shard_1_cm_test')
41
- ActiveRecord::Base.establish_connection('test')
42
- end
43
- end