switch_point 0.4.2 → 0.4.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 77687087fa3661aba6aace55de51de3f92de2e93
4
- data.tar.gz: ec806bac134278e915188fa93d988d640b8e50ac
3
+ metadata.gz: 7e586669d11f096afeeb93a78957547b262583dd
4
+ data.tar.gz: 72070196c4ca9a4ace102c2e70e24924eac98859
5
5
  SHA512:
6
- metadata.gz: e5d6a8c24fa34a4cdefd0e87786c62bc9e861beb2d848478445cb9329362b9457bfdfe06f64ad27c451a21731feddd2a7a7d70b9d4b6a361c9177701640a6a9c
7
- data.tar.gz: 90bcacff53ac17022d2494584c564daa56942f978e30fd7c0322a93063f7a193b057d241a2837767b043bae06a6f79dd96c43fc95cfa0d3cd7232333d4d9efd4
6
+ metadata.gz: bcd62b44be847b7466f31083b10eb9662061e27f33855d75bc5867ba5c12b43ac6fd57e2fb539e5a3234755540e397b9c5a3c1b30a036cbb09b60ef63d6ed282
7
+ data.tar.gz: 56249e61ef7b33a5b170680a1fd9350e8fdc42a54d051790e2c6bbb53b2056661e93c9fed7a66d9cdc1a9b4b49ef6926073f12d5dc2ba7764e27a8fbbac4ef2c
data/CHANGELOG.md CHANGED
@@ -1,3 +1,6 @@
1
+ ## 0.4.3 (2014-06-24)
2
+ - Add Model.transaction_with method (#2, @ryopeko)
3
+
1
4
  ## 0.4.2 (2014-06-19)
2
5
  - Establish connection lazily
3
6
  - Just like ActiveRecord::Base, real connection isn't created until `.connection` is called
data/README.md CHANGED
@@ -40,6 +40,11 @@ Suppose `after_save` callback is set to User model. When `User.create` is called
40
40
  - At this point, the connection is READONLY and in a transaction.
41
41
  6. COMMIT TRANSACTION is sent to READONLY connection.
42
42
 
43
+ ### connection-related methods of model
44
+ Model has several connection-related methods: `connection_handler`, `connection_pool`, `connected?` and so on.
45
+ Since only `connection` method is monkey-patched, other connection-related methods doesn't work properly.
46
+ If you'd like to use those methods, send it to `Model.switch_point_proxy.model_for_connection`.
47
+
43
48
  ## Internals
44
49
  There's a proxy which holds two connections: readonly one and writable one.
45
50
  A proxy has a thread-local state indicating the current mode: readonly or writable.
@@ -47,11 +47,36 @@ module SwitchPoint
47
47
  end
48
48
  end
49
49
 
50
+ def transaction_with(*models, &block)
51
+ unless can_transaction_with?(*models)
52
+ raise RuntimeError.new("switch_point's model names must be consistent")
53
+ end
54
+
55
+ with_writable do
56
+ self.transaction(&block)
57
+ end
58
+ end
59
+
50
60
  private
51
61
 
52
62
  def assert_existing_switch_point!(name)
53
63
  SwitchPoint.config.fetch(name)
54
64
  end
65
+
66
+ def can_transaction_with?(*models)
67
+ writable_switch_points = [self, *models].map do |model|
68
+ if model.instance_variable_defined?(:@switch_point_name)
69
+ SwitchPoint.config.model_name(
70
+ model.instance_variable_get(:@switch_point_name),
71
+ :writable
72
+ )
73
+ else
74
+ nil
75
+ end
76
+ end
77
+
78
+ writable_switch_points.uniq.size == 1
79
+ end
55
80
  end
56
81
  end
57
82
  end
@@ -120,19 +120,27 @@ module SwitchPoint
120
120
  @current_name = @initial_name
121
121
  end
122
122
 
123
- def connection
123
+ def model_for_connection
124
124
  ProxyRepository.checkout(@current_name) # Ensure the target proxy is created
125
125
  model_name = SwitchPoint.config.model_name(@current_name, mode)
126
126
  if model_name
127
- Proxy.const_get(model_name).connection
127
+ Proxy.const_get(model_name)
128
128
  elsif mode == :readonly
129
129
  # When only writable is specified, re-use writable connection.
130
130
  with_writable do
131
- connection
131
+ model_for_connection
132
132
  end
133
133
  else
134
- ActiveRecord::Base.connection
134
+ ActiveRecord::Base
135
135
  end
136
136
  end
137
+
138
+ def connection
139
+ model_for_connection.connection
140
+ end
141
+
142
+ def connected?
143
+ model_for_connection.connected?
144
+ end
137
145
  end
138
146
  end
@@ -1,3 +1,3 @@
1
1
  module SwitchPoint
2
- VERSION = "0.4.2"
2
+ VERSION = "0.4.3"
3
3
  end
data/spec/models.rb CHANGED
@@ -2,6 +2,9 @@ SwitchPoint.configure do |config|
2
2
  config.define_switch_point :main,
3
3
  readonly: :main_readonly,
4
4
  writable: :main_writable
5
+ config.define_switch_point :main2,
6
+ readonly: :main2_readonly,
7
+ writable: :main2_writable
5
8
  config.define_switch_point :user,
6
9
  readonly: :user,
7
10
  writable: :user
@@ -31,6 +34,14 @@ class Book < ActiveRecord::Base
31
34
  end
32
35
  end
33
36
 
37
+ class Book2 < ActiveRecord::Base
38
+ use_switch_point :main
39
+ end
40
+
41
+ class Book3 < ActiveRecord::Base
42
+ use_switch_point :main2
43
+ end
44
+
34
45
  class Publisher < ActiveRecord::Base
35
46
  use_switch_point :main
36
47
  end
@@ -66,6 +77,8 @@ base = { adapter: 'sqlite3' }
66
77
  ActiveRecord::Base.configurations = {
67
78
  'main_readonly' => base.merge(database: 'main_readonly.sqlite3'),
68
79
  'main_writable' => base.merge(database: 'main_writable.sqlite3'),
80
+ 'main2_readonly' => base.merge(database: 'main2_readonly.sqlite3'),
81
+ 'main2_writable' => base.merge(database: 'main2_writable.sqlite3'),
69
82
  'main_readonly_special' => base.merge(database: 'main_readonly_special.sqlite3'),
70
83
  'user' => base.merge(database: 'user.sqlite3'),
71
84
  'comment_readonly' => base.merge(database: 'comment_readonly.sqlite3'),
@@ -76,8 +89,20 @@ ActiveRecord::Base.establish_connection(:default)
76
89
 
77
90
  # XXX: Check connection laziness
78
91
  [Book, User, Note, Nanika1, ActiveRecord::Base].each do |model|
92
+ if model.connected?
93
+ raise "ActiveRecord::Base didn't establish connection lazily!"
94
+ end
95
+ end
96
+ ActiveRecord::Base.connection # Create connection
97
+
98
+ [Book, User, Nanika3].each do |model|
79
99
  model.with_writable do
80
- if model.connected?
100
+ if model.switch_point_proxy.connected?
101
+ raise "#{model.name} didn't establish connection lazily!"
102
+ end
103
+ end
104
+ model.with_readonly do
105
+ if model.switch_point_proxy.connected?
81
106
  raise "#{model.name} didn't establish connection lazily!"
82
107
  end
83
108
  end
data/spec/spec_helper.rb CHANGED
@@ -38,8 +38,19 @@ RSpec.configure do |config|
38
38
  Book.with_writable do
39
39
  Book.connection.execute('CREATE TABLE books (id integer primary key autoincrement)')
40
40
  end
41
+
42
+ Book2.with_writable do
43
+ Book2.connection.execute('CREATE TABLE book2s (id integer primary key autoincrement)')
44
+ end
45
+
41
46
  FileUtils.cp('main_writable.sqlite3', 'main_readonly.sqlite3')
42
47
 
48
+ Book3.with_writable do
49
+ Book3.connection.execute('CREATE TABLE book3s (id integer primary key autoincrement)')
50
+ end
51
+
52
+ FileUtils.cp('main2_writable.sqlite3', 'main2_readonly.sqlite3')
53
+
43
54
  Note.connection.execute('CREATE TABLE notes (id integer primary key autoincrement)')
44
55
 
45
56
  Nanika3.connection.execute('CREATE TABLE nanika3s (id integer primary key)')
@@ -261,4 +261,112 @@ RSpec.describe SwitchPoint::Model do
261
261
  end
262
262
  end
263
263
  end
264
+
265
+ describe '.transaction_with' do
266
+ context "when each model has a same writable" do
267
+ before do
268
+ @before_book_count = Book.count
269
+ @before_book2_count = Book2.count
270
+
271
+ Book.transaction_with(Book2) do
272
+ new_book = Book.create
273
+ new_book2 = Book2.create
274
+ end
275
+
276
+ @after_book_count = Book.with_writable do
277
+ Book.count
278
+ end
279
+ @after_book2_count = Book2.with_writable do
280
+ Book2.count
281
+ end
282
+ end
283
+
284
+ it 'should create a new record' do
285
+ expect(
286
+ Book.with_writable do
287
+ Book.count
288
+ end
289
+ ).to be > @before_book_count
290
+
291
+ expect(
292
+ Book2.with_writable do
293
+ Book2.count
294
+ end
295
+ ).to be > @before_book2_count
296
+ end
297
+ end
298
+
299
+ context "when each model has a other writable" do
300
+ it {
301
+ expect {
302
+ Book.transaction_with(Book3) do
303
+ new_book = Book.create
304
+ new_book3 = Book3.create
305
+ end
306
+ }.to raise_error RuntimeError
307
+ }
308
+ end
309
+
310
+ context "when raise exception in transaction that include some model, and models each have other writable" do
311
+ before do
312
+ @before_book_count = Book.count
313
+ @before_book3_count = Book3.count
314
+
315
+ Book.transaction_with(Book2) do
316
+ new_book = Book.create
317
+ new_book3 = Book3.with_writable do
318
+ Book3.create
319
+ end
320
+ raise ActiveRecord::Rollback
321
+ end
322
+ end
323
+
324
+ it 'Book should not create a new record (rollbacked)' do
325
+ expect(
326
+ Book.with_writable do
327
+ Book.count
328
+ end
329
+ ).to eq @before_book_count
330
+ end
331
+
332
+ it 'Book3 should create a new record (not rollbacked)' do
333
+ expect(
334
+ Book3.with_writable do
335
+ Book3.count
336
+ end
337
+ ).to be > @before_book3_count
338
+ end
339
+ end
340
+
341
+ context "when nested transaction_with then parent transaction rollbacked" do
342
+ before do
343
+ @before_book_count = Book.count
344
+ @before_book3_count = Book3.count
345
+
346
+ Book.transaction_with do
347
+ Book.create
348
+
349
+ Book3.transaction_with do
350
+ Book3.create
351
+ end
352
+
353
+ raise ActiveRecord::Rollback
354
+ end
355
+
356
+ it {
357
+ expect(
358
+ Book.with_writable do
359
+ Book.count
360
+ end
361
+ ).to be = @before_book_count
362
+
363
+ expect(
364
+ Book3.with_writable do
365
+ Book3.count
366
+ end
367
+ ).to be > @before_book3_count
368
+ }
369
+ end
370
+ end
371
+ end
264
372
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: switch_point
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kohei Suzuki
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-19 00:00:00.000000000 Z
11
+ date: 2014-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: appraisal