xbar 0.4.1 → 0.4.2
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/.gitignore +1 -0
- data/.rspec +2 -0
- data/README.mkdn +1 -1
- data/Rakefile +5 -2
- data/dummy/.gitignore +15 -0
- data/dummy/Gemfile +38 -0
- data/dummy/README.rdoc +261 -0
- data/dummy/Rakefile +7 -0
- data/dummy/app/assets/images/rails.png +0 -0
- data/dummy/app/assets/javascripts/application.js +15 -0
- data/dummy/app/assets/stylesheets/application.css +13 -0
- data/dummy/app/controllers/application_controller.rb +3 -0
- data/dummy/app/helpers/application_helper.rb +2 -0
- data/dummy/app/mailers/.gitkeep +0 -0
- data/dummy/app/models/.gitkeep +0 -0
- data/dummy/app/views/layouts/application.html.erb +14 -0
- data/dummy/config.ru +4 -0
- data/dummy/config/application.rb +59 -0
- data/dummy/config/boot.rb +6 -0
- data/dummy/config/database.yml +25 -0
- data/dummy/config/environment.rb +5 -0
- data/dummy/config/environments/development.rb +37 -0
- data/dummy/config/environments/production.rb +67 -0
- data/dummy/config/environments/test.rb +37 -0
- data/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/dummy/config/initializers/inflections.rb +15 -0
- data/dummy/config/initializers/mime_types.rb +5 -0
- data/dummy/config/initializers/secret_token.rb +7 -0
- data/dummy/config/initializers/session_store.rb +8 -0
- data/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/dummy/config/locales/en.yml +5 -0
- data/dummy/config/routes.rb +58 -0
- data/dummy/db/schema.rb +16 -0
- data/dummy/db/seeds.rb +7 -0
- data/dummy/doc/README_FOR_APP +2 -0
- data/dummy/lib/assets/.gitkeep +0 -0
- data/dummy/lib/generators/initializer/USAGE +8 -0
- data/dummy/lib/generators/initializer/initializer_generator.rb +8 -0
- data/dummy/lib/generators/initializer/templates/initializer.rb +1 -0
- data/dummy/lib/tasks/.gitkeep +0 -0
- data/dummy/log/.gitkeep +0 -0
- data/dummy/public/404.html +26 -0
- data/dummy/public/422.html +26 -0
- data/dummy/public/500.html +25 -0
- data/dummy/public/favicon.ico +0 -0
- data/dummy/public/index.html +241 -0
- data/dummy/public/robots.txt +5 -0
- data/dummy/script/rails +6 -0
- data/dummy/test/fixtures/.gitkeep +0 -0
- data/dummy/test/functional/.gitkeep +0 -0
- data/dummy/test/integration/.gitkeep +0 -0
- data/dummy/test/performance/browsing_test.rb +12 -0
- data/dummy/test/test_helper.rb +13 -0
- data/dummy/test/unit/.gitkeep +0 -0
- data/dummy/vendor/assets/javascripts/.gitkeep +0 -0
- data/dummy/vendor/assets/stylesheets/.gitkeep +0 -0
- data/dummy/vendor/plugins/.gitkeep +0 -0
- data/examples/README +3 -1
- data/examples/basic.rb +34 -0
- data/examples/config/canada.json +17 -0
- data/examples/config/canada2.json +17 -0
- data/examples/config/connection.rb +2 -0
- data/examples/config/simple.json +10 -10
- data/examples/lib/helpers.rb +90 -0
- data/examples/{setup.rb → lib/setup.rb} +14 -6
- data/examples/migrations/1_create_users.rb +1 -1
- data/examples/multithread.rb +47 -0
- data/examples/pause.rb +67 -0
- data/examples/pause_switch.rb +61 -0
- data/examples/switch.rb +42 -0
- data/gemfiles/rails32.gemfile.lock +3 -3
- data/lib/xbar.rb +1 -0
- data/lib/xbar/mapper.rb +61 -14
- data/lib/xbar/model.rb +1 -10
- data/lib/xbar/proxy.rb +104 -33
- data/lib/xbar/shard.rb +17 -1
- data/lib/xbar/version.rb +1 -1
- data/run +15 -7
- data/spec/console.rb +0 -1
- data/spec/spec_helper.rb +5 -2
- data/spec/xbar/association_spec.rb +1 -0
- data/spec/xbar/mapper_spec.rb +2 -4
- data/spec/xbar/model_spec.rb +11 -8
- data/spec/xbar/proxy_spec.rb +1 -1
- metadata +90 -28
- data/examples/example1.rb +0 -34
data/lib/xbar/model.rb
CHANGED
@@ -49,16 +49,11 @@ module XBar::Model
|
|
49
49
|
if new_record? || connection_proxy.in_block_scope?
|
50
50
|
if XBar.debug
|
51
51
|
type = new_record? ? "New" : "Existing"
|
52
|
-
puts "#{type} model callback, current_shard=#{connection_proxy.current_shard}, " +
|
53
|
-
"block_scope=#{connection_proxy.in_block_scope?}"
|
54
52
|
end
|
55
53
|
self.current_shard = connection_proxy.current_shard
|
56
54
|
else
|
57
55
|
if XBar.debug
|
58
56
|
type = new_record? ? "New" : "Existing"
|
59
|
-
puts "#{type} model callback, current_shard=#{connection_proxy.current_shard} " +
|
60
|
-
"last_current_shard=#{connection_proxy.last_current_shard}, " +
|
61
|
-
"block_scope=#{connection_proxy.in_block_scope?}"
|
62
57
|
end
|
63
58
|
self.current_shard = connection_proxy.last_current_shard
|
64
59
|
end
|
@@ -78,7 +73,6 @@ module XBar::Model
|
|
78
73
|
end
|
79
74
|
|
80
75
|
def connection_proxy
|
81
|
-
puts "Model allocating new connection proxy" unless Thread.current[:connection_proxy]
|
82
76
|
Thread.current[:connection_proxy] ||= XBar::Proxy.new
|
83
77
|
end
|
84
78
|
|
@@ -86,10 +80,7 @@ module XBar::Model
|
|
86
80
|
if should_use_normal_connection?
|
87
81
|
connection_without_xbar
|
88
82
|
else
|
89
|
-
|
90
|
-
#if (connection_proxy.current_model.nil?) || (self != ActiveRecord::Base)
|
91
|
-
connection_proxy.current_model = self
|
92
|
-
#end
|
83
|
+
connection_proxy.current_model = self
|
93
84
|
connection_proxy
|
94
85
|
end
|
95
86
|
end
|
data/lib/xbar/proxy.rb
CHANGED
@@ -17,27 +17,30 @@ class XBar::Proxy
|
|
17
17
|
# Setters for these are written by hand below.
|
18
18
|
attr_reader :current_model, :current_shard
|
19
19
|
|
20
|
-
attr_reader :shard_list
|
20
|
+
attr_reader :shard_list, :adapters
|
21
21
|
|
22
22
|
attr_accessor :slave_read_allowed
|
23
23
|
|
24
24
|
def initialize
|
25
|
-
|
25
|
+
if XBar.debug
|
26
|
+
puts "Proxy##{ BLUE_TEXT}{initialize}#{RESET_COLORS}: Initializing new proxy."
|
27
|
+
end
|
28
|
+
@reset = false
|
29
|
+
@pause = false
|
26
30
|
register
|
27
31
|
reset_shards
|
28
32
|
clean_proxy
|
33
|
+
@adapters = XBar::Mapper.adapters
|
34
|
+
@mylock = Mutex.new
|
35
|
+
@pause_lock = Mutex.new
|
36
|
+
@pause_cv = ConditionVariable.new
|
37
|
+
@paused = false
|
29
38
|
end
|
30
|
-
|
31
|
-
|
32
|
-
@current_shard = :master
|
33
|
-
puts ">>> reset_proxy: #{current_shard}" if XBar.debug
|
34
|
-
clear_block_scope
|
35
|
-
reset_shards
|
36
|
-
end
|
37
|
-
|
39
|
+
|
40
|
+
# Called from migration.
|
38
41
|
def clean_proxy
|
39
42
|
if XBar.debug
|
40
|
-
puts "Proxy##{BLUE_TEXT}clean_proxy
|
43
|
+
puts "Proxy##{BLUE_TEXT}clean_proxy:#{RESET_COLORS}: " +
|
41
44
|
"current shard = #{@current_shard}"
|
42
45
|
end
|
43
46
|
@current_shard = :master
|
@@ -45,12 +48,11 @@ class XBar::Proxy
|
|
45
48
|
end
|
46
49
|
|
47
50
|
def current_shard=(shard_name)
|
48
|
-
|
49
|
-
#
|
51
|
+
check_for_reset
|
52
|
+
# The shard hard name might actually be a list of shard names in
|
53
|
+
# the case of migration. Make it an array in all cases to check it.
|
50
54
|
Array(shard_name).each do |s|
|
51
55
|
if !@shard_list.member? s
|
52
|
-
puts "<<< #{@shard_list.keys} >>>"
|
53
|
-
puts "<<< #{XBar::Mapper.shards.keys} >>>"
|
54
56
|
raise "Nonexistent Shard Name: #{s}"
|
55
57
|
end
|
56
58
|
end
|
@@ -61,21 +63,6 @@ class XBar::Proxy
|
|
61
63
|
@current_shard = shard_name
|
62
64
|
end
|
63
65
|
|
64
|
-
def select_shard
|
65
|
-
if current_shard.kind_of? Array
|
66
|
-
shard = current_shard.first
|
67
|
-
if current_shard.size != 1
|
68
|
-
puts "WARNING: selecting only first shard from array"
|
69
|
-
end
|
70
|
-
else
|
71
|
-
shard = current_shard
|
72
|
-
end
|
73
|
-
unless @shard_list[shard]
|
74
|
-
puts "Shard not found: current_shard = #{shard}, @shard_list = #{@shard_list.keys}"
|
75
|
-
end
|
76
|
-
@shard_list[shard]
|
77
|
-
end
|
78
|
-
|
79
66
|
def current_model=(model)
|
80
67
|
# The way that this function is used internally, kind_of?(ActiveRecord::Base)
|
81
68
|
# is always false -- we're always passing the class.cur
|
@@ -104,7 +91,7 @@ class XBar::Proxy
|
|
104
91
|
end
|
105
92
|
|
106
93
|
def should_clean_table_name?
|
107
|
-
adapters.size > 1
|
94
|
+
@adapters.size > 1
|
108
95
|
end
|
109
96
|
|
110
97
|
def verify_connection
|
@@ -112,6 +99,8 @@ class XBar::Proxy
|
|
112
99
|
end
|
113
100
|
|
114
101
|
def run_queries_on_shard(shard_name, use_scope = true)
|
102
|
+
check_for_reset
|
103
|
+
check_for_pause
|
115
104
|
older_shard = current_shard
|
116
105
|
enter_block_scope if use_scope
|
117
106
|
self.current_shard = shard_name
|
@@ -142,6 +131,8 @@ class XBar::Proxy
|
|
142
131
|
end
|
143
132
|
|
144
133
|
def transaction(options = {}, &block)
|
134
|
+
check_for_reset
|
135
|
+
check_for_pause
|
145
136
|
select_shard.transaction(options, &block)
|
146
137
|
end
|
147
138
|
|
@@ -153,6 +144,11 @@ class XBar::Proxy
|
|
153
144
|
select_shard.quote_table_name(table_name)
|
154
145
|
end
|
155
146
|
|
147
|
+
def clear_cache!
|
148
|
+
check_for_reset
|
149
|
+
select_shard.run_queries(:clear_cache!)
|
150
|
+
end
|
151
|
+
|
156
152
|
def method_missing(method, *args, &block)
|
157
153
|
if XBar.debug
|
158
154
|
puts("\nProxy##{BLUE_TEXT}method_missing#{RESET_COLORS}: " +
|
@@ -160,7 +156,6 @@ class XBar::Proxy
|
|
160
156
|
"current_shard=#{current_shard}, " +
|
161
157
|
"in_block_scope=#{in_block_scope?}")
|
162
158
|
end
|
163
|
-
|
164
159
|
if method.to_s =~ /insert|select|execute/ && !in_block_scope? # should clean connection
|
165
160
|
shard = @last_current_shard = current_shard
|
166
161
|
clean_proxy
|
@@ -175,7 +170,9 @@ class XBar::Proxy
|
|
175
170
|
end
|
176
171
|
|
177
172
|
def connection_pool
|
178
|
-
|
173
|
+
# Or we could make a case for selecting master replica from
|
174
|
+
# the master shard, rather than the current shard. XXX.
|
175
|
+
cp = select_shard.master
|
179
176
|
cp.automatic_reconnect = true if XBar.rails31?
|
180
177
|
cp
|
181
178
|
end
|
@@ -220,6 +217,61 @@ class XBar::Proxy
|
|
220
217
|
end
|
221
218
|
end
|
222
219
|
|
220
|
+
def request_pause
|
221
|
+
@pause_lock.synchronize do
|
222
|
+
@pause = true
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
def paused?
|
227
|
+
@pause
|
228
|
+
end
|
229
|
+
|
230
|
+
def check_for_pause
|
231
|
+
if @pause && (open_transactions == 0)
|
232
|
+
@pause_lock.synchronize do
|
233
|
+
@pause = true
|
234
|
+
@pause_cv.wait(@pause_lock)
|
235
|
+
@pause = false
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
def unpause
|
241
|
+
@pause_cv.signal
|
242
|
+
end
|
243
|
+
|
244
|
+
def request_reset(opts = {})
|
245
|
+
@mylock.synchronize do
|
246
|
+
@reset = true
|
247
|
+
if opts[:hard_reset]
|
248
|
+
@hard_reset = true
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
def reset_complete?
|
254
|
+
@mylock.synchronize do
|
255
|
+
@reset == false
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
def do_reset
|
260
|
+
reset_shards
|
261
|
+
@adapters = adapters
|
262
|
+
@mylock.synchronize do
|
263
|
+
@reset = false
|
264
|
+
clean_proxy if @hard_reset
|
265
|
+
@hard_reset = false
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
def check_for_reset
|
270
|
+
if @reset && (open_transactions == 0)
|
271
|
+
do_reset
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
223
275
|
private
|
224
276
|
|
225
277
|
def reset_shards
|
@@ -234,7 +286,26 @@ class XBar::Proxy
|
|
234
286
|
slaves = replicas[1..-1] # cdr, could be empty array
|
235
287
|
@shard_list[shard_name] = XBar::Shard.new(self, shard_name, master, slaves)
|
236
288
|
end
|
289
|
+
end
|
290
|
+
|
291
|
+
def open_transactions
|
292
|
+
# The shards as known to the mapper have already changed.
|
293
|
+
@shard_list.values.inject(0) {|sum, shard| sum = shard.open_transactions}
|
294
|
+
end
|
237
295
|
|
296
|
+
def select_shard
|
297
|
+
if current_shard.kind_of? Array
|
298
|
+
shard = current_shard.first
|
299
|
+
if current_shard.size != 1
|
300
|
+
puts "WARNING: selecting only first shard from array"
|
301
|
+
end
|
302
|
+
else
|
303
|
+
shard = current_shard
|
304
|
+
end
|
305
|
+
unless @shard_list[shard]
|
306
|
+
puts "Shard not found: current_shard = #{shard}, @shard_list = #{@shard_list.keys}"
|
307
|
+
end
|
308
|
+
@shard_list[shard]
|
238
309
|
end
|
239
310
|
|
240
311
|
def insert_some_sql(conn, data)
|
data/lib/xbar/shard.rb
CHANGED
@@ -58,6 +58,22 @@ module XBar
|
|
58
58
|
master.connection.quote_table_name(table_name)
|
59
59
|
end
|
60
60
|
|
61
|
+
def open_transactions
|
62
|
+
tr_count = 0
|
63
|
+
@master.connections.inject(0) {|s, c| s + c.open_transactions}
|
64
|
+
@master.connections.each do |c|
|
65
|
+
val = c.instance_variable_get(:@_current_transaction_records) # nil or array
|
66
|
+
tr_count += val.size if val
|
67
|
+
end
|
68
|
+
@slaves.each do |s|
|
69
|
+
s.connections.each do |c|
|
70
|
+
val = c.instance_variable_get(:@_current_transaction_records) # nil or array
|
71
|
+
tr_count += val.size if val
|
72
|
+
end
|
73
|
+
end
|
74
|
+
tr_count
|
75
|
+
end
|
76
|
+
|
61
77
|
private
|
62
78
|
|
63
79
|
def prepare_connection_pool(pool)
|
@@ -96,6 +112,6 @@ module XBar
|
|
96
112
|
end
|
97
113
|
run_queries_on_replica(replica, method, *args, &block) # return sql
|
98
114
|
end
|
99
|
-
|
115
|
+
|
100
116
|
end
|
101
117
|
end
|
data/lib/xbar/version.rb
CHANGED
data/run
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
#!/bin/bash
|
2
|
-
|
3
|
-
RDEBUG=/usr/local/rvm/gems/ruby-1.9.3-p0@edge/bin/rdebug
|
4
|
-
RSPEC=/usr/local/rvm/gems/ruby-1.9.3-p0@edge/bin/rspec
|
2
|
+
|
5
3
|
SPEC_DIR="spec/xbar"
|
6
4
|
|
7
5
|
export BUNDLE_GEMFILE=/Volumes/Opt/projects/xbar/gemfiles/rails32.gemfile
|
@@ -11,9 +9,14 @@ LINE=$2
|
|
11
9
|
|
12
10
|
if [ -n "$SPEC" ]
|
13
11
|
then
|
14
|
-
|
12
|
+
if [ "$SPEC" = "all" ]
|
13
|
+
then
|
14
|
+
TEST="all"
|
15
|
+
else
|
16
|
+
TEST="$SPEC_DIR/${SPEC}_spec.rb"
|
17
|
+
fi
|
15
18
|
else
|
16
|
-
echo "run.sh spec [line]"
|
19
|
+
echo "run.sh spec [line] | all"
|
17
20
|
exit 1
|
18
21
|
fi
|
19
22
|
|
@@ -22,6 +25,11 @@ then
|
|
22
25
|
TEST="${TEST}:${LINE}"
|
23
26
|
fi
|
24
27
|
|
25
|
-
|
28
|
+
if [ "$SPEC" == "all" ]
|
29
|
+
then
|
30
|
+
bundle exec ruby -S rspec -fd -b -c ./spec/xbar/*_spec.rb
|
31
|
+
else
|
32
|
+
bundle exec ruby -S rspec -fd -b -c ${TEST}
|
33
|
+
fi
|
34
|
+
|
26
35
|
|
27
|
-
bundle exec ${RUBY} ${RSPEC} -fd -b -c ${TEST}
|
data/spec/console.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -5,15 +5,18 @@ require "active_record"
|
|
5
5
|
require "action_controller"
|
6
6
|
require "xbar"
|
7
7
|
require "support/xbar_helper"
|
8
|
-
require "support/database_models"
|
9
8
|
|
10
9
|
MIGRATIONS_ROOT = File.expand_path(File.join(File.dirname(__FILE__), 'migrations'))
|
11
10
|
|
12
|
-
XBar.directory = File.expand_path(
|
11
|
+
XBar.directory = File.expand_path(File.dirname(__FILE__))
|
12
|
+
|
13
|
+
# Must be after setting the XBar directory.
|
14
|
+
require "support/database_models"
|
13
15
|
|
14
16
|
RSpec.configure do |config|
|
15
17
|
|
16
18
|
config.before(:each) do
|
19
|
+
# XBar.directory = File.expand_path(File.dirname(__FILE__))
|
17
20
|
XBar.stub!(:directory).and_return(File.dirname(__FILE__))
|
18
21
|
end
|
19
22
|
|
@@ -337,6 +337,7 @@ describe XBar::Association do
|
|
337
337
|
role = @new_brazil_programmer.projects.create(:name => "New VB App :-/")
|
338
338
|
@new_brazil_programmer.projects.find(:first).should == role
|
339
339
|
@new_brazil_programmer.projects.destroy_all
|
340
|
+
sleep(0.5) # Replication delay sometimes causes a spurious failure
|
340
341
|
@new_brazil_programmer.projects.find(:first).should be_nil
|
341
342
|
end
|
342
343
|
|
data/spec/xbar/mapper_spec.rb
CHANGED
@@ -16,7 +16,7 @@ describe XBar::Mapper do
|
|
16
16
|
end
|
17
17
|
|
18
18
|
it "should return all environments" do
|
19
|
-
XBar::Mapper.environments.should == ["test", "development", "staging"]
|
19
|
+
XBar::Mapper.environments.should == ["test", "development", "staging", "local_test"]
|
20
20
|
end
|
21
21
|
|
22
22
|
it "should work with thinking sphinx" do
|
@@ -259,16 +259,14 @@ describe XBar::Mapper do
|
|
259
259
|
end
|
260
260
|
|
261
261
|
end
|
262
|
-
|
263
|
-
|
264
262
|
end
|
265
|
-
|
266
263
|
end
|
267
264
|
|
268
265
|
describe "when you specify a bogus application environment" do
|
269
266
|
before(:each) do
|
270
267
|
set_xbar_env("acme", "bogus")
|
271
268
|
@proxy = Thread.current[:connection_proxy]
|
269
|
+
@proxy.check_for_reset
|
272
270
|
end
|
273
271
|
|
274
272
|
it "should initialize the list of shards" do
|
data/spec/xbar/model_spec.rb
CHANGED
@@ -79,14 +79,12 @@ describe XBar::Model do
|
|
79
79
|
end
|
80
80
|
|
81
81
|
it "should allow creating more than one user" do
|
82
|
-
XBar.debug = true
|
83
82
|
User.using(:canada).create([{ :name => 'America User 1' }, { :name => 'America User 2' }])
|
84
83
|
User.create!(:name => "Thiago")
|
85
84
|
User.using(:canada).find_by_name("America User 1").should_not be_nil
|
86
85
|
User.using(:canada).find_by_name("America User 2")#.should_not be_nil
|
87
86
|
User.using(:master).find_by_name("Thiago").should_not be_nil
|
88
87
|
User.all.size.should == 1 # fail -- America User 2 is being created on master!!!
|
89
|
-
XBar.debug = false
|
90
88
|
end
|
91
89
|
|
92
90
|
it "should work when you have a SQLite3 shard" do
|
@@ -340,7 +338,7 @@ describe XBar::Model do
|
|
340
338
|
describe "when using a environment with a single adapter" do
|
341
339
|
before (:each) do
|
342
340
|
set_xbar_env('single_adapter', 'test')
|
343
|
-
@proxy = XBar::Proxy.new
|
341
|
+
@proxy = Thread.current[:connection_proxy] || XBar::Proxy.new
|
344
342
|
end
|
345
343
|
|
346
344
|
it 'should_clean_table_name? should return false' do
|
@@ -361,8 +359,9 @@ describe XBar::Model do
|
|
361
359
|
end
|
362
360
|
|
363
361
|
describe "when you have joins/include" do
|
364
|
-
|
362
|
+
|
365
363
|
before(:each) do
|
364
|
+
set_xbar_env('default', 'test')
|
366
365
|
|
367
366
|
@client1 = Client.using(:brazil).create(:name => "Thiago")
|
368
367
|
|
@@ -381,7 +380,8 @@ describe XBar::Model do
|
|
381
380
|
end
|
382
381
|
|
383
382
|
it "should work with the rails 2.x syntax" do
|
384
|
-
items = Item.using(:canada).find(:all, :joins => :client,
|
383
|
+
items = Item.using(:canada).find(:all, :joins => :client,
|
384
|
+
:conditions => { :clients => { :id => @client2.id } })
|
385
385
|
items.should == [@item1, @item2]
|
386
386
|
end
|
387
387
|
|
@@ -393,7 +393,8 @@ describe XBar::Model do
|
|
393
393
|
end
|
394
394
|
|
395
395
|
it "should work for include also, rails 2.x syntax" do
|
396
|
-
items = Item.using(:canada).find(:all, :include => :client,
|
396
|
+
items = Item.using(:canada).find(:all, :include => :client,
|
397
|
+
:conditions => { :clients => { :id => @client2.id } })
|
397
398
|
items.should == [@item1, @item2]
|
398
399
|
end
|
399
400
|
|
@@ -405,13 +406,15 @@ describe XBar::Model do
|
|
405
406
|
end
|
406
407
|
|
407
408
|
it "should work for multiple includes, with rails 2.x syntax" do
|
408
|
-
parts = Part.using(:canada).find(:all, :include => {:item => :client},
|
409
|
+
parts = Part.using(:canada).find(:all, :include => {:item => :client},
|
410
|
+
:conditions => {:clients => { :id => @client2.id}})
|
409
411
|
parts.should == [@part1, @part2, @part3]
|
410
412
|
parts.first.item.client.should == @client2
|
411
413
|
end
|
412
414
|
|
413
415
|
it "should work for multiple join, with rails 2.x syntax" do
|
414
|
-
parts = Part.using(:canada).find(:all, :joins => {:item => :client},
|
416
|
+
parts = Part.using(:canada).find(:all, :joins => {:item => :client},
|
417
|
+
:conditions => {:clients => { :id => @client2.id}})
|
415
418
|
parts.should == [@part1, @part2, @part3]
|
416
419
|
parts.first.item.client.should == @client2
|
417
420
|
end
|