ar-octopus 0.3.4 → 0.4.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.
data/lib/octopus.rb CHANGED
@@ -11,10 +11,16 @@ module Octopus
11
11
  end
12
12
 
13
13
  def self.config()
14
- @config ||= HashWithIndifferentAccess.new(YAML.load(ERB.new(File.open(Octopus.directory() + "/config/shards.yml").read()).result))[Octopus.env()]
14
+ file_name = Octopus.directory() + "/config/shards.yml"
15
15
 
16
- if @config && @config['environments']
17
- self.environments = @config['environments']
16
+ if File.exists? file_name
17
+ @config ||= HashWithIndifferentAccess.new(YAML.load(ERB.new(File.open(file_name).read()).result))[Octopus.env()]
18
+
19
+ if @config && @config['environments']
20
+ self.environments = @config['environments']
21
+ end
22
+ else
23
+ @config ||= HashWithIndifferentAccess.new
18
24
  end
19
25
 
20
26
  @config
@@ -49,6 +55,12 @@ module Octopus
49
55
  defined?(Rails)
50
56
  end
51
57
 
58
+ def self.shards=(shards)
59
+ @config ||= HashWithIndifferentAccess.new
60
+ @config[rails_env()] = HashWithIndifferentAccess.new(shards)
61
+ ActiveRecord::Base.connection.initialize_shards(@config)
62
+ end
63
+
52
64
  def self.using(shard, &block)
53
65
  ActiveRecord::Base.hijack_initializer()
54
66
  conn = ActiveRecord::Base.connection
@@ -71,6 +83,7 @@ require "octopus/association"
71
83
  if Octopus.rails3?
72
84
  require "octopus/rails3/association"
73
85
  require "octopus/rails3/persistence"
86
+ require "octopus/rails3/arel"
74
87
  else
75
88
  require "octopus/rails2/association"
76
89
  require "octopus/rails2/persistence"
@@ -78,4 +91,4 @@ end
78
91
 
79
92
  require "octopus/proxy"
80
93
  require "octopus/scope_proxy"
81
-
94
+ require "octopus/logger"
@@ -0,0 +1,14 @@
1
+ require "logger"
2
+
3
+ class Octopus::Logger < Logger
4
+ def format_message(severity, timestamp, progname, msg)
5
+ str = super
6
+
7
+ if ActiveRecord::Base.connection.respond_to?(:current_shard)
8
+ str += "Shard: #{ActiveRecord::Base.connection.current_shard} -"
9
+ end
10
+
11
+ str
12
+ end
13
+ end
14
+
data/lib/octopus/model.rb CHANGED
@@ -7,14 +7,22 @@ module Octopus::Model
7
7
 
8
8
  module SharedMethods
9
9
  def clean_table_name
10
- self.reset_table_name() if self != ActiveRecord::Base && self.respond_to?(:reset_table_name)
10
+ return unless self.connection_proxy.should_clean_table_name?
11
+ if self != ActiveRecord::Base && self.respond_to?(:reset_table_name) && !self.read_inheritable_attribute(:set_table_name)
12
+ self.reset_table_name()
13
+ end
14
+
15
+ if Octopus.rails3?
16
+ self.reset_column_information
17
+ self.instance_variable_set(:@quoted_table_name, nil)
18
+ end
11
19
  end
12
20
 
13
21
  def using(shard)
14
22
  return self if defined?(::Rails) && !Octopus.environments.include?(Rails.env.to_s)
15
23
 
16
- clean_table_name()
17
24
  hijack_initializer() if !respond_to?(:set_current_shard)
25
+ clean_table_name()
18
26
 
19
27
  self.connection_proxy.using_enabled = true
20
28
 
@@ -23,7 +31,6 @@ module Octopus::Model
23
31
 
24
32
  def hijack_initializer()
25
33
  attr_accessor :current_shard
26
- after_initialize :set_current_shard
27
34
  before_save :reload_connection
28
35
 
29
36
  def set_current_shard
@@ -34,7 +41,9 @@ module Octopus::Model
34
41
  end
35
42
  end
36
43
 
37
- if !Octopus.rails3?
44
+ if Octopus.rails3?
45
+ after_initialize :set_current_shard
46
+ else
38
47
  def after_initialize
39
48
  set_current_shard()
40
49
  end
@@ -90,7 +99,12 @@ module Octopus::Model
90
99
  write_inheritable_attribute(:establish_connection, true)
91
100
  establish_connection(spec)
92
101
  end
102
+
103
+ def octopus_set_table_name(value = nil, &block)
104
+ write_inheritable_attribute(:set_table_name, true)
105
+ set_table_name(value, &block)
106
+ end
93
107
  end
94
108
  end
95
109
 
96
- ActiveRecord::Base.extend(Octopus::Model)
110
+ ActiveRecord::Base.extend(Octopus::Model)
data/lib/octopus/proxy.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require "set"
2
+
1
3
  class Octopus::Proxy
2
4
  attr_accessor :current_model, :current_shard, :current_group, :block, :using_enabled, :last_current_shard, :config
3
5
 
@@ -7,8 +9,9 @@ class Octopus::Proxy
7
9
  end
8
10
 
9
11
  def initialize_shards(config)
10
- @shards = {}
11
- @groups = {}
12
+ @shards = HashWithIndifferentAccess.new
13
+ @groups = HashWithIndifferentAccess.new
14
+ @adapters = Set.new
12
15
  @shards[:master] = ActiveRecord::Base.connection_pool()
13
16
  @config = ActiveRecord::Base.connection_pool.connection.instance_variable_get(:@config)
14
17
  @current_shard = :master
@@ -87,6 +90,10 @@ class Octopus::Proxy
87
90
  current_shard.is_a?(Array) ? current_shard.first : current_shard
88
91
  end
89
92
 
93
+ def should_clean_table_name?
94
+ @adapters.size > 1
95
+ end
96
+
90
97
  def run_queries_on_shard(shard, &block)
91
98
  older_shard = self.current_shard
92
99
  last_block = self.block
@@ -143,12 +150,17 @@ class Octopus::Proxy
143
150
  end
144
151
  end
145
152
 
153
+ def respond_to?(method, include_private = false)
154
+ super || select_connection.respond_to?(method, include_private)
155
+ end
156
+
146
157
  protected
147
158
  def connection_pool_for(adapter, config)
148
159
  ActiveRecord::ConnectionAdapters::ConnectionPool.new(ActiveRecord::Base::ConnectionSpecification.new(adapter, config))
149
160
  end
150
161
 
151
162
  def initialize_adapter(adapter)
163
+ @adapters << adapter
152
164
  begin
153
165
  require "active_record/connection_adapters/#{adapter}_adapter"
154
166
  rescue LoadError
@@ -167,16 +179,19 @@ class Octopus::Proxy
167
179
  def send_queries_to_selected_slave(method, *args, &block)
168
180
  old_shard = self.current_shard
169
181
 
170
- if current_model.read_inheritable_attribute(:replicated) || @fully_replicated
171
- self.current_shard = @slaves_list.shift.to_sym
172
- @slaves_list << self.current_shard
173
- else
174
- self.current_shard = :master
175
- end
182
+ begin
183
+ if current_model.read_inheritable_attribute(:replicated) || @fully_replicated
184
+ self.current_shard = @slaves_list.shift.to_sym
185
+ @slaves_list << self.current_shard
186
+ else
187
+ self.current_shard = :master
188
+ end
176
189
 
177
- sql = select_connection().send(method, *args, &block)
178
- self.current_shard = old_shard
179
- @using_enabled = nil
180
- return sql
190
+ sql = select_connection().send(method, *args, &block)
191
+ return sql
192
+ ensure
193
+ self.current_shard = old_shard
194
+ @using_enabled = nil
195
+ end
181
196
  end
182
197
  end
@@ -0,0 +1,13 @@
1
+ class Arel::Visitors::ToSql
2
+ def quote value, column = nil
3
+ ActiveRecord::Base.connection.quote value, column
4
+ end
5
+
6
+ def quote_table_name name
7
+ ActiveRecord::Base.connection.quote_table_name(name)
8
+ end
9
+
10
+ def quote_column_name name
11
+ Arel::Nodes::SqlLiteral === name ? name : ActiveRecord::Base.connection.quote_column_name(name)
12
+ end
13
+ end
@@ -24,11 +24,11 @@ class Octopus::ScopeProxy
24
24
  @klass.connection()
25
25
  end
26
26
 
27
- def method_missing(method, *args, &block)
27
+ def method_missing(method, *args, &block)
28
28
  @klass.connection.run_queries_on_shard(@shard) do
29
29
  @klass = @klass.send(method, *args, &block)
30
30
  end
31
-
31
+
32
32
  return @klass if @klass.is_a?(ActiveRecord::Base) or @klass.is_a?(Array) or @klass.is_a?(Fixnum) or @klass.nil?
33
33
  return self
34
34
  end
@@ -37,4 +37,4 @@ class Octopus::ScopeProxy
37
37
  @shard == other.shard
38
38
  @klass == other.klass
39
39
  end
40
- end
40
+ end
data/sample_app/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
1
  source :rubygems
2
2
 
3
- gem 'rails', '3.0.0'
3
+ gem 'rails', '3.0.5'
4
4
 
5
5
  # Bundle edge Rails instead:
6
6
  # gem 'rails', :git => 'git://github.com/rails/rails.git'
@@ -18,4 +18,4 @@ group :test do
18
18
  gem "rspec-rails", ">= 2.0.0.beta.16"
19
19
  gem 'ruby-debug' if RUBY_VERSION < "1.9"
20
20
  gem "aruba"
21
- end
21
+ end
@@ -1,130 +1,146 @@
1
1
  GIT
2
2
  remote: git://github.com/tchandy/octopus.git
3
- revision: ff16c71
3
+ revision: 13320d08a1d722f1cd4d12468b328a59367a2c88
4
4
  specs:
5
- ar-octopus (0.1.0)
5
+ ar-octopus (0.3.4)
6
6
  activerecord (>= 2.3)
7
7
 
8
8
  GEM
9
9
  remote: http://rubygems.org/
10
10
  specs:
11
11
  abstract (1.0.0)
12
- actionmailer (3.0.0)
13
- actionpack (= 3.0.0)
14
- mail (~> 2.2.5)
15
- actionpack (3.0.0)
16
- activemodel (= 3.0.0)
17
- activesupport (= 3.0.0)
12
+ actionmailer (3.0.5)
13
+ actionpack (= 3.0.5)
14
+ mail (~> 2.2.15)
15
+ actionpack (3.0.5)
16
+ activemodel (= 3.0.5)
17
+ activesupport (= 3.0.5)
18
18
  builder (~> 2.1.2)
19
19
  erubis (~> 2.6.6)
20
- i18n (~> 0.4.1)
20
+ i18n (~> 0.4)
21
21
  rack (~> 1.2.1)
22
- rack-mount (~> 0.6.12)
23
- rack-test (~> 0.5.4)
22
+ rack-mount (~> 0.6.13)
23
+ rack-test (~> 0.5.7)
24
24
  tzinfo (~> 0.3.23)
25
- activemodel (3.0.0)
26
- activesupport (= 3.0.0)
25
+ activemodel (3.0.5)
26
+ activesupport (= 3.0.5)
27
27
  builder (~> 2.1.2)
28
- i18n (~> 0.4.1)
29
- activerecord (3.0.0)
30
- activemodel (= 3.0.0)
31
- activesupport (= 3.0.0)
32
- arel (~> 1.0.0)
28
+ i18n (~> 0.4)
29
+ activerecord (3.0.5)
30
+ activemodel (= 3.0.5)
31
+ activesupport (= 3.0.5)
32
+ arel (~> 2.0.2)
33
33
  tzinfo (~> 0.3.23)
34
- activeresource (3.0.0)
35
- activemodel (= 3.0.0)
36
- activesupport (= 3.0.0)
37
- activesupport (3.0.0)
38
- arel (1.0.1)
39
- activesupport (~> 3.0.0)
40
- aruba (0.2.1)
34
+ activeresource (3.0.5)
35
+ activemodel (= 3.0.5)
36
+ activesupport (= 3.0.5)
37
+ activesupport (3.0.5)
38
+ arel (2.0.9)
39
+ aruba (0.2.7)
40
+ background_process
41
+ cucumber (~> 0.10.0)
42
+ background_process (1.2)
41
43
  builder (2.1.2)
42
- capybara (0.3.9)
44
+ capybara (0.4.1.2)
45
+ celerity (>= 0.7.9)
43
46
  culerity (>= 0.2.4)
44
47
  mime-types (>= 1.16)
45
48
  nokogiri (>= 1.3.3)
46
49
  rack (>= 1.0.0)
47
50
  rack-test (>= 0.5.4)
48
- selenium-webdriver (>= 0.0.3)
49
- columnize (0.3.1)
50
- configuration (1.1.0)
51
- cucumber (0.8.5)
52
- builder (~> 2.1.2)
51
+ selenium-webdriver (>= 0.0.27)
52
+ xpath (~> 0.1.3)
53
+ celerity (0.8.8)
54
+ childprocess (0.1.7)
55
+ ffi (~> 0.6.3)
56
+ columnize (0.3.2)
57
+ configuration (1.2.0)
58
+ cucumber (0.10.0)
59
+ builder (>= 2.1.2)
53
60
  diff-lcs (~> 1.1.2)
54
- gherkin (~> 2.1.4)
55
- json_pure (~> 1.4.3)
56
- term-ansicolor (~> 1.0.4)
61
+ gherkin (~> 2.3.2)
62
+ json (~> 1.4.6)
63
+ term-ansicolor (~> 1.0.5)
57
64
  cucumber-rails (0.3.2)
58
65
  cucumber (>= 0.8.0)
59
- culerity (0.2.12)
60
- database_cleaner (0.5.2)
66
+ culerity (0.2.15)
67
+ database_cleaner (0.6.4)
61
68
  diff-lcs (1.1.2)
62
69
  erubis (2.6.6)
63
70
  abstract (>= 1.0.0)
64
71
  ffi (0.6.3)
65
72
  rake (>= 0.8.7)
66
- gherkin (2.1.5)
67
- trollop (~> 1.16.2)
68
- i18n (0.4.1)
69
- json_pure (1.4.6)
73
+ gherkin (2.3.3)
74
+ json (~> 1.4.6)
75
+ i18n (0.5.0)
76
+ json (1.4.6)
77
+ json_pure (1.5.1)
70
78
  launchy (0.3.7)
71
79
  configuration (>= 0.0.5)
72
80
  rake (>= 0.8.1)
73
81
  linecache (0.43)
74
- mail (2.2.5)
82
+ mail (2.2.15)
75
83
  activesupport (>= 2.3.6)
76
- mime-types
77
- treetop (>= 1.4.5)
84
+ i18n (>= 0.4.0)
85
+ mime-types (~> 1.16)
86
+ treetop (~> 1.4.8)
78
87
  mime-types (1.16)
79
- nokogiri (1.4.3.1)
88
+ nokogiri (1.4.4)
80
89
  polyglot (0.3.1)
81
90
  rack (1.2.1)
82
91
  rack-mount (0.6.13)
83
92
  rack (>= 1.0.0)
84
- rack-test (0.5.4)
93
+ rack-test (0.5.7)
85
94
  rack (>= 1.0)
86
- rails (3.0.0)
87
- actionmailer (= 3.0.0)
88
- actionpack (= 3.0.0)
89
- activerecord (= 3.0.0)
90
- activeresource (= 3.0.0)
91
- activesupport (= 3.0.0)
92
- bundler (~> 1.0.0)
93
- railties (= 3.0.0)
94
- railties (3.0.0)
95
- actionpack (= 3.0.0)
96
- activesupport (= 3.0.0)
97
- rake (>= 0.8.4)
98
- thor (~> 0.14.0)
95
+ rails (3.0.5)
96
+ actionmailer (= 3.0.5)
97
+ actionpack (= 3.0.5)
98
+ activerecord (= 3.0.5)
99
+ activeresource (= 3.0.5)
100
+ activesupport (= 3.0.5)
101
+ bundler (~> 1.0)
102
+ railties (= 3.0.5)
103
+ railties (3.0.5)
104
+ actionpack (= 3.0.5)
105
+ activesupport (= 3.0.5)
106
+ rake (>= 0.8.7)
107
+ thor (~> 0.14.4)
99
108
  rake (0.8.7)
100
- rspec (2.0.0.beta.20)
101
- rspec-core (= 2.0.0.beta.20)
102
- rspec-expectations (= 2.0.0.beta.20)
103
- rspec-mocks (= 2.0.0.beta.20)
104
- rspec-core (2.0.0.beta.20)
105
- rspec-expectations (2.0.0.beta.20)
106
- diff-lcs (>= 1.1.2)
107
- rspec-mocks (2.0.0.beta.20)
108
- rspec-rails (2.0.0.beta.20)
109
- rspec (= 2.0.0.beta.20)
110
- ruby-debug (0.10.3)
109
+ rspec (2.5.0)
110
+ rspec-core (~> 2.5.0)
111
+ rspec-expectations (~> 2.5.0)
112
+ rspec-mocks (~> 2.5.0)
113
+ rspec-core (2.5.1)
114
+ rspec-expectations (2.5.0)
115
+ diff-lcs (~> 1.1.2)
116
+ rspec-mocks (2.5.0)
117
+ rspec-rails (2.5.0)
118
+ actionpack (~> 3.0)
119
+ activesupport (~> 3.0)
120
+ railties (~> 3.0)
121
+ rspec (~> 2.5.0)
122
+ ruby-debug (0.10.4)
111
123
  columnize (>= 0.1)
112
- ruby-debug-base (~> 0.10.3.0)
113
- ruby-debug-base (0.10.3)
124
+ ruby-debug-base (~> 0.10.4.0)
125
+ ruby-debug-base (0.10.4)
114
126
  linecache (>= 0.3)
115
127
  rubyzip (0.9.4)
116
- selenium-webdriver (0.0.28)
117
- ffi (>= 0.6.1)
128
+ selenium-webdriver (0.1.3)
129
+ childprocess (~> 0.1.5)
130
+ ffi (~> 0.6.3)
118
131
  json_pure
119
132
  rubyzip
120
133
  spork (0.8.4)
121
- sqlite3-ruby (1.3.1)
134
+ sqlite3 (1.3.3)
135
+ sqlite3-ruby (1.3.3)
136
+ sqlite3 (>= 1.3.3)
122
137
  term-ansicolor (1.0.5)
123
- thor (0.14.0)
124
- treetop (1.4.8)
138
+ thor (0.14.6)
139
+ treetop (1.4.9)
125
140
  polyglot (>= 0.3.1)
126
- trollop (1.16.2)
127
- tzinfo (0.3.23)
141
+ tzinfo (0.3.24)
142
+ xpath (0.1.3)
143
+ nokogiri (~> 1.3)
128
144
 
129
145
  PLATFORMS
130
146
  ruby
@@ -137,7 +153,7 @@ DEPENDENCIES
137
153
  cucumber-rails
138
154
  database_cleaner
139
155
  launchy
140
- rails (= 3.0.0)
156
+ rails (= 3.0.5)
141
157
  rspec-rails (>= 2.0.0.beta.16)
142
158
  ruby-debug
143
159
  spork