ar-octopus 0.0.24 → 0.0.25
Sign up to get free protection for your applications and to get access to all the features.
- data/README.mkdn +26 -24
- data/Rakefile +11 -2
- data/ar-octopus.gemspec +12 -3
- data/lib/octopus.rb +13 -13
- data/lib/octopus/association.rb +18 -4
- data/lib/octopus/migration.rb +5 -2
- data/lib/octopus/model.rb +5 -14
- data/lib/octopus/proxy.rb +8 -12
- data/lib/octopus/rails3/persistence.rb +0 -4
- data/spec/config/shards.yml +1 -1
- data/spec/database_models.rb +5 -0
- data/spec/octopus/association_spec.rb +136 -0
- data/spec/octopus/proxy_spec.rb +5 -4
- data/spec/octopus_helper.rb +7 -2
- metadata +54 -7
data/README.mkdn
CHANGED
@@ -1,26 +1,26 @@
|
|
1
|
-
|
1
|
+
# Octopus - Easy Database Sharding for ActiveRecord
|
2
2
|
|
3
|
-
|
3
|
+
Octopus is a better way to do Database Sharding in ActiveRecord. Sharding allows multiple databases in the same rails application. While there are several projects that implement Sharding (e.g. DbCharmer, DataFabric, MultiDb), each project has its own limitations. The main goal of octopus project is to provide a nice and clean way of doing Database Sharding.
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
## Feature list:
|
6
|
+
The design of the api is made to be simple as possible. Octopus is focusing in the end user, giving the power of multiple databases, but with reliable code and flexibility. Octopus is focused on Rails 3, but is compatible with Rails 2.x.
|
7
7
|
|
8
|
-
|
8
|
+
Octopus supports:
|
9
9
|
|
10
10
|
- Sharding (with multiple shards, and grouped shards).
|
11
11
|
- Replication (Master/slave support, with multiple slaves).
|
12
12
|
- Moving data between shards with migrations.
|
13
13
|
- Tools to manage database configurations. (soon)
|
14
14
|
|
15
|
-
|
16
|
-
|
15
|
+
### Replication
|
16
|
+
When using replication, all writes queries will be sent to master, and read queries to slaves. More info could be found at: <a href="http://wiki.github.com/tchandy/octopus/replication"> Wiki</a>
|
17
17
|
|
18
|
-
|
19
|
-
|
18
|
+
### Sharding
|
19
|
+
When using sharding, you need to specify what shard the query will be sent. Octopus support selecting the shard inside a controller, or manually in each object. More could be found at <a href="http://wiki.github.com/tchandy/octopus/sharding"> Wiki</a>
|
20
20
|
|
21
|
-
|
21
|
+
## Install
|
22
22
|
|
23
|
-
|
23
|
+
### Rails 2.x
|
24
24
|
|
25
25
|
Install the octopus gem:
|
26
26
|
<pre> sudo gem install ar-octopus </pre>
|
@@ -28,7 +28,7 @@ Install the octopus gem:
|
|
28
28
|
Add this line to enviroment.rb:
|
29
29
|
<pre>config.gem 'ar-octopus', :lib => "octopus"</pre>
|
30
30
|
|
31
|
-
|
31
|
+
### Rails 3.x
|
32
32
|
|
33
33
|
Add this line to Gemfile:
|
34
34
|
<pre>gem 'ar-octopus', :require => "octopus"</pre>
|
@@ -36,21 +36,23 @@ Add this line to Gemfile:
|
|
36
36
|
Runs a bundle install:
|
37
37
|
<pre>bundle install</pre>
|
38
38
|
|
39
|
-
|
40
|
-
<p>First, you need to create a config file, shards.yml, inside your config/ directory. to see the syntax and how this file should look, please checkout <a href="http://wiki.github.com/tchandy/octopus/config-file">this page on wiki</a></p>.
|
39
|
+
## How to use Octopus?
|
41
40
|
|
42
|
-
<
|
43
|
-
|
41
|
+
First, you need to create a config file, shards.yml, inside your config/ directory. to see the syntax and how this file should look, please checkout <a href="http://wiki.github.com/tchandy/octopus/config-file">this page on wiki</a>.
|
42
|
+
|
43
|
+
### Syntax
|
44
|
+
|
45
|
+
Octopus adds a method to each AR Class and object. the using method is used to select the shard, like this:
|
44
46
|
<pre>User.where(:name => "Thiago").limit(3).using(:slave_one) </pre>
|
45
47
|
|
46
|
-
|
48
|
+
Octopus also supports queries inside block. When you pass a block to the using method, all queries inside the block will be sent to the specified shard.
|
47
49
|
<pre>
|
48
50
|
User.using(:slave_two) do
|
49
51
|
User.create(:name => "Mike")
|
50
52
|
end
|
51
53
|
</pre>
|
52
54
|
|
53
|
-
|
55
|
+
Each object knows where is your shard, so you could to thinks like this:
|
54
56
|
<pre>
|
55
57
|
# This will find the user in the shard1
|
56
58
|
@user = User.using(:shard1).find_by_name("Joao")
|
@@ -65,7 +67,7 @@ end
|
|
65
67
|
@user.save()
|
66
68
|
</pre>
|
67
69
|
|
68
|
-
|
70
|
+
In migrations, you also have access to the using method. The syntax is basically the same. This migration will run in brazil and canada shards.
|
69
71
|
<pre>
|
70
72
|
class CreateUsersOnBothShards < ActiveRecord::Migration
|
71
73
|
using(:brazil, :canada)
|
@@ -79,7 +81,7 @@ end
|
|
79
81
|
end
|
80
82
|
end
|
81
83
|
</pre>
|
82
|
-
|
84
|
+
You also could send a migration to a group of shards. This migration will be sent to all shards that belongs to history_shards group, specified in shards.yml:
|
83
85
|
<pre>
|
84
86
|
class CreateUsersOnMultiplesGroups < ActiveRecord::Migration
|
85
87
|
using_group(:history_shards)
|
@@ -94,14 +96,14 @@ end
|
|
94
96
|
end
|
95
97
|
</pre>
|
96
98
|
|
97
|
-
|
98
|
-
|
99
|
+
To see the complete list of features and syntax, please check out our <a href="http://wiki.github.com/tchandy/octopus/"> Wiki</a>
|
100
|
+
Wanna see sample rails applications using octopus features? please check it out: <a href="http://github.com/tchandy/octopus_sharding_example">Sharding Example</a> and <a href="http://github.com/tchandy/octopus_replication_example">Replication Example</a>
|
99
101
|
|
100
|
-
|
102
|
+
## Thanks
|
101
103
|
|
102
104
|
This project is sponsored by the <a href="http://www.rubysoc.org">Ruby Summer of Code</a>,
|
103
105
|
and my mentors <a href="http://github.com/mperham">Mike Perham</a> and <a href="http://github.com/amitagarwal">Amit Agarwal</a>.
|
104
106
|
|
105
|
-
|
107
|
+
## Copyright
|
106
108
|
|
107
109
|
Copyright (c) 2010 Thiago Pradi, released under the MIT license.
|
data/Rakefile
CHANGED
@@ -26,10 +26,13 @@ begin
|
|
26
26
|
gem.description = "This gem allows you to use sharded databases with ActiveRecord. this also provides a interface for replication and for running migrations with multiples shards."
|
27
27
|
gem.email = "tchandy@gmail.com"
|
28
28
|
gem.homepage = "http://github.com/tchandy/octopus"
|
29
|
-
gem.authors = ["Thiago Pradi", "Mike Perham"
|
29
|
+
gem.authors = ["Thiago Pradi", "Mike Perham"]
|
30
30
|
gem.add_development_dependency "rspec", ">= 1.2.9"
|
31
|
+
gem.add_development_dependency "mysql", ">= 2.8.1"
|
32
|
+
gem.add_development_dependency "pg", ">= 0.9.0"
|
33
|
+
gem.add_development_dependency "sqlite3-ruby", ">= 1.3.1"
|
31
34
|
gem.add_dependency('activerecord', '>= 3.0.0beta')
|
32
|
-
gem.version = "0.0.
|
35
|
+
gem.version = "0.0.25"
|
33
36
|
end
|
34
37
|
Jeweler::GemcutterTasks.new
|
35
38
|
rescue LoadError
|
@@ -147,6 +150,12 @@ namespace :db do
|
|
147
150
|
ActiveRecord::Base.using(shard_symbol).connection.create_table(:projects) do |u|
|
148
151
|
u.string :name
|
149
152
|
end
|
153
|
+
|
154
|
+
ActiveRecord::Base.using(shard_symbol).connection.create_table(:comments) do |u|
|
155
|
+
u.string :name
|
156
|
+
u.string :commentable_type
|
157
|
+
u.integer :commentable_id
|
158
|
+
end
|
150
159
|
end
|
151
160
|
end
|
152
161
|
|
data/ar-octopus.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{ar-octopus}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.25"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
-
s.authors = ["Thiago Pradi", "Mike Perham"
|
12
|
-
s.date = %q{2010-07-
|
11
|
+
s.authors = ["Thiago Pradi", "Mike Perham"]
|
12
|
+
s.date = %q{2010-07-16}
|
13
13
|
s.description = %q{This gem allows you to use sharded databases with ActiveRecord. this also provides a interface for replication and for running migrations with multiples shards.}
|
14
14
|
s.email = %q{tchandy@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -107,13 +107,22 @@ Gem::Specification.new do |s|
|
|
107
107
|
|
108
108
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
109
109
|
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
110
|
+
s.add_development_dependency(%q<mysql>, [">= 2.8.1"])
|
111
|
+
s.add_development_dependency(%q<pg>, [">= 0.9.0"])
|
112
|
+
s.add_development_dependency(%q<sqlite3-ruby>, [">= 1.3.1"])
|
110
113
|
s.add_runtime_dependency(%q<activerecord>, [">= 3.0.0beta"])
|
111
114
|
else
|
112
115
|
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
116
|
+
s.add_dependency(%q<mysql>, [">= 2.8.1"])
|
117
|
+
s.add_dependency(%q<pg>, [">= 0.9.0"])
|
118
|
+
s.add_dependency(%q<sqlite3-ruby>, [">= 1.3.1"])
|
113
119
|
s.add_dependency(%q<activerecord>, [">= 3.0.0beta"])
|
114
120
|
end
|
115
121
|
else
|
116
122
|
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
123
|
+
s.add_dependency(%q<mysql>, [">= 2.8.1"])
|
124
|
+
s.add_dependency(%q<pg>, [">= 0.9.0"])
|
125
|
+
s.add_dependency(%q<sqlite3-ruby>, [">= 1.3.1"])
|
117
126
|
s.add_dependency(%q<activerecord>, [">= 3.0.0beta"])
|
118
127
|
end
|
119
128
|
end
|
data/lib/octopus.rb
CHANGED
@@ -2,20 +2,20 @@ require "yaml"
|
|
2
2
|
|
3
3
|
module Octopus
|
4
4
|
def self.env()
|
5
|
-
|
5
|
+
@env ||= 'octopus'
|
6
6
|
end
|
7
|
-
|
7
|
+
|
8
8
|
def self.rails_env()
|
9
9
|
@rails_env ||= self.rails? ? Rails.env.to_s : 'shards'
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
def self.config()
|
13
|
-
@config ||= HashWithIndifferentAccess.new(YAML.load_file(Octopus.directory() + "/config/shards.yml"))
|
14
|
-
|
15
|
-
if
|
16
|
-
self.enviroments = @config[
|
13
|
+
@config ||= HashWithIndifferentAccess.new(YAML.load_file(Octopus.directory() + "/config/shards.yml"))[Octopus.env()]
|
14
|
+
|
15
|
+
if @config && @config['enviroments']
|
16
|
+
self.enviroments = @config['enviroments']
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
@config
|
20
20
|
end
|
21
21
|
|
@@ -24,26 +24,26 @@ module Octopus
|
|
24
24
|
def self.directory()
|
25
25
|
@directory ||= defined?(Rails) ? Rails.root.to_s : Dir.pwd
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
# This is the default way to do Octopus Setup
|
29
29
|
# Available variables:
|
30
30
|
# :enviroments => the enviroments that octopus will run. default: :production
|
31
31
|
def self.setup
|
32
32
|
yield self
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
def self.enviroments=(enviroments)
|
36
36
|
@enviroments = enviroments.map { |element| element.to_s }
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
def self.enviroments
|
40
40
|
@enviroments || ['production']
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
def self.rails3?
|
44
44
|
ActiveRecord::VERSION::MAJOR == 3
|
45
45
|
end
|
46
|
-
|
46
|
+
|
47
47
|
def self.rails?
|
48
48
|
defined?(Rails)
|
49
49
|
end
|
data/lib/octopus/association.rb
CHANGED
@@ -1,4 +1,14 @@
|
|
1
1
|
module Octopus::Association
|
2
|
+
def self.extended(base)
|
3
|
+
base.send(:include, InstanceMethods)
|
4
|
+
end
|
5
|
+
|
6
|
+
module InstanceMethods
|
7
|
+
def set_connection_on_association(record)
|
8
|
+
record.current_shard = self.connection.current_shard = self.current_shard if should_set_current_shard?
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
2
12
|
def has_many(association_id, options = {}, &extension)
|
3
13
|
default_octopus_opts(options)
|
4
14
|
super
|
@@ -11,15 +21,19 @@ module Octopus::Association
|
|
11
21
|
|
12
22
|
def default_octopus_opts(options)
|
13
23
|
if options[:before_add].is_a?(Array)
|
14
|
-
options[:before_add] << :
|
24
|
+
options[:before_add] << :set_connection_on_association
|
25
|
+
elsif options[:before_add].is_a?(Symbol)
|
26
|
+
options[:before_add] = [:set_connection_on_association, options[:before_add]]
|
15
27
|
else
|
16
|
-
options[:before_add] = :
|
28
|
+
options[:before_add] = :set_connection_on_association
|
17
29
|
end
|
18
30
|
|
19
31
|
if options[:before_remove].is_a?(Array)
|
20
|
-
options[:before_remove] << :
|
32
|
+
options[:before_remove] << :set_connection_on_association
|
33
|
+
elsif options[:before_remove].is_a?(Symbol)
|
34
|
+
options[:before_remove] = [:set_connection_on_association, options[:before_remove]]
|
21
35
|
else
|
22
|
-
options[:before_remove] = :
|
36
|
+
options[:before_remove] = :set_connection_on_association
|
23
37
|
end
|
24
38
|
end
|
25
39
|
end
|
data/lib/octopus/migration.rb
CHANGED
@@ -7,6 +7,7 @@ module Octopus::Migration
|
|
7
7
|
|
8
8
|
alias_method_chain :migrate, :octopus
|
9
9
|
alias_method_chain :announce, :octopus
|
10
|
+
attr_accessor :current_shard
|
10
11
|
end
|
11
12
|
end
|
12
13
|
|
@@ -17,6 +18,7 @@ module Octopus::Migration
|
|
17
18
|
end
|
18
19
|
|
19
20
|
self.connection().block = true
|
21
|
+
self.current_shard = args
|
20
22
|
self.connection().current_shard = args
|
21
23
|
end
|
22
24
|
|
@@ -51,11 +53,12 @@ module Octopus::Migration
|
|
51
53
|
|
52
54
|
def migrate_with_octopus(direction)
|
53
55
|
conn = ActiveRecord::Base.connection
|
56
|
+
return migrate_without_octopus(direction) unless conn.is_a?(Octopus::Proxy)
|
57
|
+
self.connection().current_shard = self.current_shard if self.current_shard != nil
|
58
|
+
|
54
59
|
groups = conn.instance_variable_get(:@groups)
|
55
60
|
|
56
61
|
begin
|
57
|
-
return migrate_without_octopus(direction) unless conn.is_a?(Octopus::Proxy)
|
58
|
-
|
59
62
|
if conn.current_group.is_a?(Array)
|
60
63
|
conn.current_group.each { |group| conn.send_queries_to_multiple_shards(groups[group]) { migrate_without_octopus(direction) } }
|
61
64
|
elsif conn.current_group.is_a?(Symbol)
|
data/lib/octopus/model.rb
CHANGED
@@ -33,13 +33,13 @@ module Octopus::Model
|
|
33
33
|
def hijack_initializer()
|
34
34
|
attr_accessor :current_shard
|
35
35
|
after_initialize :set_current_shard
|
36
|
-
before_save :
|
36
|
+
before_save :reload_connection
|
37
37
|
|
38
38
|
def set_current_shard
|
39
39
|
if new_record? || self.connection.block
|
40
|
-
self.current_shard = self.
|
40
|
+
self.current_shard = self.connection.current_shard
|
41
41
|
else
|
42
|
-
self.current_shard = self.
|
42
|
+
self.current_shard = self.connection.last_current_shard
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
@@ -75,21 +75,12 @@ module Octopus::Model
|
|
75
75
|
module InstanceMethods
|
76
76
|
include SharedMethods
|
77
77
|
|
78
|
-
def set_connection(*args)
|
79
|
-
if(args.size == 1)
|
80
|
-
arg = args.first
|
81
|
-
arg.current_shard = self.current_shard if arg.respond_to?(:current_shard) && should_set_current_shard?
|
82
|
-
end
|
83
|
-
|
84
|
-
self.connection.current_shard = self.current_shard if should_set_current_shard?
|
85
|
-
end
|
86
|
-
|
87
78
|
def should_set_current_shard?
|
88
|
-
self.respond_to?(:current_shard) && self.current_shard
|
79
|
+
self.respond_to?(:current_shard) && !self.current_shard.nil?
|
89
80
|
end
|
90
81
|
|
91
82
|
def reload_connection()
|
92
|
-
|
83
|
+
self.connection.current_shard = self.current_shard() if should_set_current_shard?
|
93
84
|
end
|
94
85
|
end
|
95
86
|
|
data/lib/octopus/proxy.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
class Octopus::Proxy
|
2
2
|
attr_accessor :current_model, :current_shard, :current_group, :block, :using_enabled, :last_current_shard
|
3
3
|
|
4
|
-
def initialize(config)
|
4
|
+
def initialize(config)
|
5
5
|
initialize_shards(config)
|
6
|
-
initialize_replication(config) if
|
6
|
+
initialize_replication(config) if !config.nil? && config["replicated"]
|
7
7
|
end
|
8
8
|
|
9
9
|
def initialize_shards(config)
|
@@ -12,10 +12,10 @@ class Octopus::Proxy
|
|
12
12
|
@shards[:master] = ActiveRecord::Base.connection_pool()
|
13
13
|
@current_shard = :master
|
14
14
|
|
15
|
-
if
|
16
|
-
shards_config = config[
|
17
|
-
elsif
|
18
|
-
shards_config = config[
|
15
|
+
if !config.nil? && Octopus.rails?
|
16
|
+
shards_config = config[Rails.env().to_s]["shards"]
|
17
|
+
elsif !config.nil?
|
18
|
+
shards_config = config["shards"]
|
19
19
|
end
|
20
20
|
|
21
21
|
shards_config ||= []
|
@@ -39,7 +39,7 @@ class Octopus::Proxy
|
|
39
39
|
|
40
40
|
def initialize_replication(config)
|
41
41
|
@replicated = true
|
42
|
-
@entire_replicated = config[
|
42
|
+
@entire_replicated = config["entire_replicated"]
|
43
43
|
@slaves_list = @shards.keys.map {|sym| sym.to_s}.sort
|
44
44
|
@slaves_list.delete('master')
|
45
45
|
end
|
@@ -135,16 +135,12 @@ class Octopus::Proxy
|
|
135
135
|
end
|
136
136
|
|
137
137
|
def should_clean_connection?(method)
|
138
|
-
method.to_s =~ /insert|select|execute/ &&
|
138
|
+
method.to_s =~ /insert|select|execute/ && !@replicated && !self.block
|
139
139
|
end
|
140
140
|
|
141
141
|
def should_send_queries_to_replicated_databases?(method)
|
142
142
|
@replicated && method.to_s =~ /select/
|
143
143
|
end
|
144
|
-
|
145
|
-
def have_config_for_enviroment?(config)
|
146
|
-
!config[Octopus.env()].nil?
|
147
|
-
end
|
148
144
|
|
149
145
|
def send_queries_to_selected_slave(method, *args, &block)
|
150
146
|
old_shard = self.current_shard
|
data/spec/config/shards.yml
CHANGED
data/spec/database_models.rb
CHANGED
@@ -10,6 +10,7 @@ end
|
|
10
10
|
#The client class isn't replicated
|
11
11
|
class Client < ActiveRecord::Base
|
12
12
|
has_many :items
|
13
|
+
has_many :comments, :as => :commentable
|
13
14
|
end
|
14
15
|
|
15
16
|
#This class is replicated
|
@@ -52,4 +53,8 @@ end
|
|
52
53
|
class Project < ActiveRecord::Base
|
53
54
|
has_many :assignments
|
54
55
|
has_many :programmers, :through => :assignments
|
56
|
+
end
|
57
|
+
|
58
|
+
class Comment < ActiveRecord::Base
|
59
|
+
belongs_to :commentable, :polymorphic => true
|
55
60
|
end
|
@@ -503,4 +503,140 @@ describe Octopus::Association do
|
|
503
503
|
end
|
504
504
|
end
|
505
505
|
end
|
506
|
+
|
507
|
+
describe "when you have a 1 x N polymorphic relationship" do
|
508
|
+
before(:each) do
|
509
|
+
@brazil_client = Client.using(:brazil).create!(:name => "Brazil Client")
|
510
|
+
@master_client = Client.create!(:name => "Master Client")
|
511
|
+
@comment_brazil = Comment.using(:brazil).create!(:name => "Brazil Comment", :commentable => @brazil_client)
|
512
|
+
@comment_master = Comment.create!(:name => "Master Comment", :commentable => @master_client)
|
513
|
+
@brazil_client = Client.using(:brazil).find_by_name("Brazil Client")
|
514
|
+
Client.using(:master).create!(:name => "teste")
|
515
|
+
end
|
516
|
+
|
517
|
+
it "should find all models in the specified shard" do
|
518
|
+
@brazil_client.comment_ids.should == [@comment_brazil.id]
|
519
|
+
@brazil_client.comments().should == [@comment_brazil]
|
520
|
+
end
|
521
|
+
|
522
|
+
it "should finds the client that the comment belongs" do
|
523
|
+
@comment_brazil.commentable.should == @brazil_client
|
524
|
+
end
|
525
|
+
|
526
|
+
it "should update the attribute for the comment" do
|
527
|
+
new_brazil_client = Client.using(:brazil).create!(:name => "new Client")
|
528
|
+
@comment_brazil.commentable = new_brazil_client
|
529
|
+
@comment_brazil.commentable.should == new_brazil_client
|
530
|
+
@comment_brazil.save()
|
531
|
+
@comment_brazil.reload
|
532
|
+
@comment_brazil.commentable_id.should == new_brazil_client.id
|
533
|
+
@comment_brazil.commentable().should == new_brazil_client
|
534
|
+
end
|
535
|
+
|
536
|
+
describe "it should works when using" do
|
537
|
+
before(:each) do
|
538
|
+
@comment_brazil_2 = Comment.using(:brazil).create!(:name => "Brazil Comment 2")
|
539
|
+
@brazil_client.comments.to_set.should == [@comment_brazil].to_set
|
540
|
+
end
|
541
|
+
|
542
|
+
it "update_attributes" do
|
543
|
+
@brazil_client.update_attributes(:comment_ids => [@comment_brazil_2.id, @comment_brazil.id])
|
544
|
+
@brazil_client.comments.to_set.should == [@comment_brazil, @comment_brazil_2].to_set
|
545
|
+
end
|
546
|
+
|
547
|
+
it "update_attribute" do
|
548
|
+
@brazil_client.update_attribute(:comment_ids, [@comment_brazil_2.id, @comment_brazil.id])
|
549
|
+
@brazil_client.comments.to_set.should == [@comment_brazil, @comment_brazil_2].to_set
|
550
|
+
end
|
551
|
+
|
552
|
+
it "<<" do
|
553
|
+
@brazil_client.comments << @comment_brazil_2
|
554
|
+
@brazil_client.comments.to_set.should == [@comment_brazil, @comment_brazil_2].to_set
|
555
|
+
end
|
556
|
+
|
557
|
+
it "build" do
|
558
|
+
comment = @brazil_client.comments.build(:name => "Builded Comment")
|
559
|
+
comment.save()
|
560
|
+
@brazil_client.comments.to_set.should == [@comment_brazil, comment].to_set
|
561
|
+
end
|
562
|
+
|
563
|
+
it "create" do
|
564
|
+
comment = @brazil_client.comments.create(:name => "Builded Comment")
|
565
|
+
@brazil_client.comments.to_set.should == [@comment_brazil, comment].to_set
|
566
|
+
end
|
567
|
+
|
568
|
+
it "count" do
|
569
|
+
@brazil_client.comments.count.should == 1
|
570
|
+
comment = @brazil_client.comments.create(:name => "Builded Comment")
|
571
|
+
@brazil_client.comments.count.should == 2
|
572
|
+
end
|
573
|
+
|
574
|
+
it "size" do
|
575
|
+
@brazil_client.comments.size.should == 1
|
576
|
+
comment = @brazil_client.comments.create(:name => "Builded Comment")
|
577
|
+
@brazil_client.comments.size.should == 2
|
578
|
+
end
|
579
|
+
|
580
|
+
it "create!" do
|
581
|
+
comment = @brazil_client.comments.create!(:name => "Builded Comment")
|
582
|
+
@brazil_client.comments.to_set.should == [@comment_brazil, comment].to_set
|
583
|
+
end
|
584
|
+
|
585
|
+
it "length" do
|
586
|
+
@brazil_client.comments.length.should == 1
|
587
|
+
comment = @brazil_client.comments.create(:name => "Builded Comment")
|
588
|
+
@brazil_client.comments.length.should == 2
|
589
|
+
end
|
590
|
+
|
591
|
+
it "empty?" do
|
592
|
+
@brazil_client.comments.empty?.should be_false
|
593
|
+
c = Client.create!(:name => "Client1")
|
594
|
+
c.comments.empty?.should be_true
|
595
|
+
end
|
596
|
+
|
597
|
+
it "delete" do
|
598
|
+
@brazil_client.comments.empty?.should be_false
|
599
|
+
@brazil_client.comments.delete(@comment_brazil)
|
600
|
+
@brazil_client.reload
|
601
|
+
@comment_brazil.reload
|
602
|
+
@comment_brazil.commentable.should be_nil
|
603
|
+
@brazil_client.comments.should == []
|
604
|
+
@brazil_client.comments.empty?.should be_true
|
605
|
+
end
|
606
|
+
|
607
|
+
it "delete_all" do
|
608
|
+
@brazil_client.comments.empty?.should be_false
|
609
|
+
@brazil_client.comments.delete_all
|
610
|
+
@brazil_client.comments.empty?.should be_true
|
611
|
+
end
|
612
|
+
|
613
|
+
it "destroy_all" do
|
614
|
+
@brazil_client.comments.empty?.should be_false
|
615
|
+
@brazil_client.comments.destroy_all
|
616
|
+
@brazil_client.comments.empty?.should be_true
|
617
|
+
end
|
618
|
+
|
619
|
+
it "find" do
|
620
|
+
@brazil_client.comments.find(:first).should == @comment_brazil
|
621
|
+
@brazil_client.comments.destroy_all
|
622
|
+
@brazil_client.comments.find(:first).should be_nil
|
623
|
+
end
|
624
|
+
|
625
|
+
it "exists?" do
|
626
|
+
@brazil_client.comments.exists?(@comment_brazil).should be_true
|
627
|
+
@brazil_client.comments.destroy_all
|
628
|
+
@brazil_client.comments.exists?(@comment_brazil).should be_false
|
629
|
+
end
|
630
|
+
|
631
|
+
it "uniq" do
|
632
|
+
@brazil_client.comments.uniq.should == [@comment_brazil]
|
633
|
+
end
|
634
|
+
|
635
|
+
it "clear" do
|
636
|
+
@brazil_client.comments.empty?.should be_false
|
637
|
+
@brazil_client.comments.clear
|
638
|
+
@brazil_client.comments.empty?.should be_true
|
639
|
+
end
|
640
|
+
end
|
641
|
+
end
|
506
642
|
end
|
data/spec/octopus/proxy_spec.rb
CHANGED
@@ -19,7 +19,7 @@ describe Octopus::Proxy do
|
|
19
19
|
|
20
20
|
describe "should raise error if you have duplicated shard names" do
|
21
21
|
before(:each) do
|
22
|
-
|
22
|
+
set_octopus_env("production_raise_error")
|
23
23
|
end
|
24
24
|
|
25
25
|
it "should raise the error" do
|
@@ -29,7 +29,7 @@ describe Octopus::Proxy do
|
|
29
29
|
|
30
30
|
describe "should initialize just the master when you don't have a shards.yml file" do
|
31
31
|
before(:each) do
|
32
|
-
|
32
|
+
set_octopus_env("crazy_enviroment")
|
33
33
|
end
|
34
34
|
|
35
35
|
it "should initialize just the master shard" do
|
@@ -48,7 +48,7 @@ describe Octopus::Proxy do
|
|
48
48
|
|
49
49
|
describe "when you have a replicated enviroment" do
|
50
50
|
before(:each) do
|
51
|
-
|
51
|
+
set_octopus_env("production_replicated")
|
52
52
|
end
|
53
53
|
|
54
54
|
it "should have the replicated attribute as true" do
|
@@ -63,7 +63,7 @@ describe Octopus::Proxy do
|
|
63
63
|
describe "when you have a rails application" do
|
64
64
|
before(:each) do
|
65
65
|
Rails = mock()
|
66
|
-
|
66
|
+
set_octopus_env("octopus_rails")
|
67
67
|
end
|
68
68
|
|
69
69
|
it "should initialize correctly octopus common variables for the enviroments" do
|
@@ -88,6 +88,7 @@ describe Octopus::Proxy do
|
|
88
88
|
|
89
89
|
after(:each) do
|
90
90
|
Object.send(:remove_const, :Rails)
|
91
|
+
Octopus.instance_variable_set(:@config, nil)
|
91
92
|
end
|
92
93
|
end
|
93
94
|
|
data/spec/octopus_helper.rb
CHANGED
@@ -21,11 +21,16 @@ end
|
|
21
21
|
|
22
22
|
def using_enviroment(enviroment, &block)
|
23
23
|
begin
|
24
|
-
|
24
|
+
set_octopus_env(enviroment.to_s)
|
25
25
|
clean_connection_proxy()
|
26
26
|
yield
|
27
27
|
ensure
|
28
|
-
|
28
|
+
set_octopus_env('octopus')
|
29
29
|
clean_connection_proxy()
|
30
30
|
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def set_octopus_env(env)
|
34
|
+
Octopus.instance_variable_set(:@config, nil)
|
35
|
+
Octopus.stub!(:env).and_return(env)
|
31
36
|
end
|
metadata
CHANGED
@@ -1,23 +1,22 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ar-octopus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 45
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 25
|
10
|
+
version: 0.0.25
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Thiago Pradi
|
14
14
|
- Mike Perham
|
15
|
-
- Amit Agarwal
|
16
15
|
autorequire:
|
17
16
|
bindir: bin
|
18
17
|
cert_chain: []
|
19
18
|
|
20
|
-
date: 2010-07-
|
19
|
+
date: 2010-07-16 00:00:00 -03:00
|
21
20
|
default_executable:
|
22
21
|
dependencies:
|
23
22
|
- !ruby/object:Gem::Dependency
|
@@ -37,9 +36,57 @@ dependencies:
|
|
37
36
|
type: :development
|
38
37
|
version_requirements: *id001
|
39
38
|
- !ruby/object:Gem::Dependency
|
40
|
-
name:
|
39
|
+
name: mysql
|
41
40
|
prerelease: false
|
42
41
|
requirement: &id002 !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
hash: 45
|
47
|
+
segments:
|
48
|
+
- 2
|
49
|
+
- 8
|
50
|
+
- 1
|
51
|
+
version: 2.8.1
|
52
|
+
type: :development
|
53
|
+
version_requirements: *id002
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: pg
|
56
|
+
prerelease: false
|
57
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
hash: 59
|
63
|
+
segments:
|
64
|
+
- 0
|
65
|
+
- 9
|
66
|
+
- 0
|
67
|
+
version: 0.9.0
|
68
|
+
type: :development
|
69
|
+
version_requirements: *id003
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: sqlite3-ruby
|
72
|
+
prerelease: false
|
73
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
hash: 25
|
79
|
+
segments:
|
80
|
+
- 1
|
81
|
+
- 3
|
82
|
+
- 1
|
83
|
+
version: 1.3.1
|
84
|
+
type: :development
|
85
|
+
version_requirements: *id004
|
86
|
+
- !ruby/object:Gem::Dependency
|
87
|
+
name: activerecord
|
88
|
+
prerelease: false
|
89
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
43
90
|
none: false
|
44
91
|
requirements:
|
45
92
|
- - ">="
|
@@ -51,7 +98,7 @@ dependencies:
|
|
51
98
|
- 0beta
|
52
99
|
version: 3.0.0beta
|
53
100
|
type: :runtime
|
54
|
-
version_requirements: *
|
101
|
+
version_requirements: *id005
|
55
102
|
description: This gem allows you to use sharded databases with ActiveRecord. this also provides a interface for replication and for running migrations with multiples shards.
|
56
103
|
email: tchandy@gmail.com
|
57
104
|
executables: []
|