remotable 0.6.3 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0bc89a5dd898f5030f0ced00996be9fe97cf9f56f4817b664feff997b45be1eb
4
- data.tar.gz: 317441824b1507700cd77f17a8a623a472145ee458a3aa6fc68e820f2a0ae1c9
3
+ metadata.gz: 63584474c5b00a857f670dee818ce28a13afc86ab2cb5aaf6a57bac41bc307d9
4
+ data.tar.gz: f8737d89d220a3055f48e46b664da8faba882fee0e24532cc2895bf44f3ab32f
5
5
  SHA512:
6
- metadata.gz: 69072c80830b9bad844d0d1e2347875577c9de503edc8c0b5c28898e2f9612d5697e089365bd8e554e4dc53375445ba6a813d3c2d8df4619873c72ae327dc1cf
7
- data.tar.gz: 8b5c7e8760947917691c089d19004b8c665f9fa5abaa35873fe9d203247a832f882ee10e7c39059f249aa34133cf8e79140c745aaf3c2bf082e43495d3187583
6
+ metadata.gz: ff131813baeba52877f45c3ce493ec219d0e31583eb0571622f96e6a4c29f350cf4a582c8b6cb06848e9e463e49731fdb27cacbdd6df1dd2a1d49396be1e8e1b
7
+ data.tar.gz: 38f6a48221d360eb17026c128ce70f1e6db301c73540055b9a50c28b4049bd5c3e6ca6c8e9efed9c87103e055243a75e8d80d041607e31706d61125632191c2d
@@ -0,0 +1,39 @@
1
+ name: Tests
2
+ on: [push]
3
+ jobs:
4
+ rails:
5
+ name: Rails Tests
6
+ runs-on: ubuntu-latest
7
+ strategy:
8
+ matrix:
9
+ ruby: [2.6, 2.7, "3.0"]
10
+ gemfile: ["gemfiles/rails_6.0.gemfile", "gemfiles/rails_6.1.gemfile"]
11
+ fail-fast: false
12
+ env:
13
+ GEM_HOME: $HOME/.gem
14
+ steps:
15
+ - name: Checkout
16
+ uses: actions/checkout@v2
17
+
18
+ - name: Setup Ruby
19
+ uses: ruby/setup-ruby@v1
20
+ with:
21
+ ruby-version: ${{ matrix.ruby }}
22
+ bundler: 2.2.14
23
+ bundler-cache: true
24
+
25
+ - name: Clean appraisals
26
+ run: bundle exec appraisal clean
27
+
28
+ # We'll let appraisal generate our gemfiles
29
+ - name: Generate gemfiles
30
+ run: bundle exec appraisal generate
31
+
32
+ # We'll only install the gems for our non-rails-edge tests, those can be run locally
33
+ # This will overwrite the Gemfile.lock in the root app directory, with the gem versions we need for the test
34
+ - name: Install gemfile dependencies
35
+ run: BUNDLE_GEMFILE=${{ matrix.gemfile }} bundle install
36
+
37
+ - name: Run the tests
38
+ id: tests
39
+ run: bundle exec rake test
data/Appraisals CHANGED
@@ -1,23 +1,13 @@
1
- appraise "rails-5.0" do
2
- gem "activerecord", "~> 5.0.0"
3
- gem "sqlite3", "~> 1.3.6"
4
- end
5
-
6
- appraise "rails-5.1" do
7
- gem "activerecord", "~> 5.1.0"
8
- gem "sqlite3", "~> 1.3.6"
9
- end
10
-
11
- appraise "rails-5.2" do
12
- gem "activerecord", "~> 5.2.0"
13
- gem "sqlite3", "~> 1.3.6"
14
- end
15
-
16
1
  appraise "rails-6.0" do
17
2
  gem "activerecord", "~> 6.0.0"
18
3
  gem "sqlite3", "~> 1.4.0"
19
4
  end
20
5
 
6
+ appraise "rails-6.1" do
7
+ gem "activerecord", "~> 6.1"
8
+ gem "sqlite3", "~> 1.4.0"
9
+ end
10
+
21
11
  appraise "rails-edge" do
22
12
  gem "rails", git: "https://github.com/rails/rails.git", branch: "master", require: "activerecord"
23
13
  gem "sqlite3", "~> 1.4.0"
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ### 0.7.0
4
+ * **Bugfix** Ensured ActiveRecord models were using Nosync's `ClassMethods` instead of the non-threadsafe `InstanceMethods`
5
+
6
+ ### 0.6.4
7
+ * **Feature** Added `Remotable.unsafe_nosync!` method to set `nosync` globally using a class variable. As the method name indicates, this is not threadsafe and should only be used for testing or other situations where thread safety is not an issue.
8
+ * **Bugfix** Stopped deferring to `Thread.main` if `nosync` was unset on the current thread; while convenient for tests (see above), it ended up allowing requests to leak state if they were handled on the main thread.
9
+
10
+
3
11
  ### 0.6.3
4
12
  * **Fix** Replaced deprecated calls to URI.escape
5
13
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  source "http://rubygems.org"
4
4
 
5
- gem "activerecord", "~> 5.0.0"
6
- gem "sqlite3", "~> 1.3.6"
5
+ gem "activerecord", "~> 6.1"
6
+ gem "sqlite3", "~> 1.4.0"
7
7
 
8
8
  gemspec path: "../"
@@ -2,7 +2,6 @@
2
2
 
3
3
  source "http://rubygems.org"
4
4
 
5
- gem "rails", git: "https://github.com/rails/rails.git", branch: "master", require: "activerecord"
6
5
  gem "sqlite3", "~> 1.4.0"
7
6
 
8
7
  gemspec path: "../"
@@ -17,6 +17,16 @@ module Remotable
17
17
 
18
18
 
19
19
  included do
20
+ extend Nosync
21
+
22
+ # Has to be re-defined _after_ Nosync is extended, which cannot
23
+ # be done as part of the ClassMethods module
24
+ def self.nosync?
25
+ return true if remote_model.nil?
26
+ return super if nosync_value?
27
+ Remotable.nosync?
28
+ end
29
+
20
30
  before_update :update_remote_resource, :unless => :nosync?
21
31
  before_create :create_remote_resource, :unless => :nosync?
22
32
  before_destroy :destroy_remote_resource, :unless => :nosync?
@@ -41,16 +51,10 @@ module Remotable
41
51
 
42
52
 
43
53
  module ClassMethods
44
- include Nosync
45
54
 
46
55
  attr_accessor :_remote_attribute_map, :_local_attribute_routes, :_expires_after,
47
56
  :_remote_timeout, :remotable_skip_validation_on_sync
48
57
 
49
- def nosync?
50
- return true if remote_model.nil?
51
- return super if nosync_value?
52
- Remotable.nosync?
53
- end
54
58
 
55
59
  # Sets the key with which a resource is identified remotely.
56
60
  # If no remote key is set, the remote key is assumed to be :id.
@@ -606,7 +610,7 @@ module Remotable
606
610
 
607
611
  def merge_remote_errors(errors)
608
612
  Remotable.logger.debug "[remotable:#{self.class.name.underscore}:merge_remote_errors](#{fetch_value.inspect}) #{errors.inspect}"
609
- errors.each do |attribute, messages|
613
+ errors.to_h.each do |attribute, messages|
610
614
  Array.wrap(messages).each do |message|
611
615
  self.errors.add(local_attribute_name(attribute), message)
612
616
  end
@@ -50,8 +50,14 @@ module Remotable
50
50
  module ClassMethods
51
51
  include InstanceMethods
52
52
 
53
+ def unsafe_nosync!
54
+ nosync!
55
+ @_unsafe_nosync = true
56
+ end
57
+
53
58
  def reset_nosync!
54
59
  self.nosync = nil
60
+ remove_instance_variable :@_unsafe_nosync if instance_variable_defined? :@_unsafe_nosync
55
61
  end
56
62
 
57
63
  def nosync=(val)
@@ -62,7 +68,7 @@ module Remotable
62
68
 
63
69
  def _nosync
64
70
  return Thread.current.thread_variable_get "remotable.nosync.#{self.object_id}" if nosync_defined_on?(Thread.current)
65
- return Thread.main.thread_variable_get "remotable.nosync.#{self.object_id}" if nosync_defined_on?(Thread.main)
71
+ @_unsafe_nosync if instance_variable_defined?(:@_unsafe_nosync)
66
72
  end
67
73
 
68
74
  def _nosync=(value)
@@ -1,3 +1,3 @@
1
1
  module Remotable
2
- VERSION = "0.6.3"
2
+ VERSION = "0.9.0"
3
3
  end
data/remotable.gemspec CHANGED
@@ -11,13 +11,13 @@ Gem::Specification.new do |s|
11
11
  s.summary = %q{Binds an ActiveRecord model to a remote resource and keeps the two synchronized}
12
12
  s.description = %q{Remotable keeps a locally-stored ActiveRecord synchronized with a remote resource.}
13
13
 
14
- s.add_dependency "activeresource", ">= 3.2"
14
+ s.add_dependency "activeresource", ">= 5.1.1"
15
15
  s.add_dependency "activerecord"
16
16
  s.add_dependency "activesupport"
17
17
 
18
18
  s.add_development_dependency "appraisal"
19
19
  s.add_development_dependency "rake"
20
- s.add_development_dependency "minitest", "~> 5.10.3"
20
+ s.add_development_dependency "minitest", "~> 5.14.4"
21
21
  s.add_development_dependency "minitest-reporters"
22
22
  s.add_development_dependency "minitest-reporters-turn_reporter"
23
23
  s.add_development_dependency "pry"
data/test/bespoke_test.rb CHANGED
@@ -176,7 +176,7 @@ class BespokeTest < ActiveSupport::TestCase
176
176
 
177
177
  assert_difference "BespokeTenant.count", -1 do
178
178
  @tenant = BespokeTenant.find_by_slug(@tenant.slug)
179
- assert_equal nil, @tenant
179
+ assert_nil @tenant
180
180
  end
181
181
  end
182
182
 
data/test/nosync_test.rb CHANGED
@@ -48,11 +48,9 @@ class NoSyncTest < ActiveSupport::TestCase
48
48
  assert_equal true, Tenant.nosync?
49
49
  end
50
50
 
51
- test "nosync? should defer to the main thread's value if set there but not on the current thread" do
51
+ test "nosync? should not defer to the main thread's value if set there but not on the current thread" do
52
52
  Remotable.nosync!
53
53
  subthread = Thread.new do
54
- assert Remotable.nosync?
55
- Remotable.reset_nosync!
56
54
  refute Remotable.nosync?
57
55
  Thread.stop
58
56
  end
@@ -60,6 +58,16 @@ class NoSyncTest < ActiveSupport::TestCase
60
58
  assert Remotable.nosync?
61
59
  end
62
60
 
61
+ test "unsafe_nosync! should coerce nosync? to true across threads" do
62
+ Remotable.unsafe_nosync!
63
+ subthread = Thread.new do
64
+ assert Remotable.nosync?
65
+ Thread.stop
66
+ end
67
+ sleep 0.1 while subthread.status != "sleep"
68
+ assert Remotable.nosync?
69
+ end
70
+
63
71
 
64
72
 
65
73
  # ========================================================================= #
@@ -52,7 +52,7 @@ class RemotableTest < ActiveSupport::TestCase
52
52
  test "should support setting remote_model to nil" do
53
53
  Tenant.with_remote_model(nil) do
54
54
  Tenant.remote_model
55
- assert_equal nil, Tenant.remote_model, "remote_model didn't get set to nil"
55
+ assert_nil Tenant.remote_model, "remote_model didn't get set to nil"
56
56
  Tenant.create!(:name => "Test 1", :slug => "test-1")
57
57
  assert_not_nil Tenant.find_by_name("Test 1"), "new tenant was not found"
58
58
  end
@@ -68,6 +68,13 @@ class RemotableTest < ActiveSupport::TestCase
68
68
 
69
69
  concurrently do
70
70
  assert_nil BespokeTenant.find_by_slug(first_slug), "Expected not to find the first model initially"
71
+ # If the second thread attempts the above lookup after the first thread
72
+ # has already run the lookup below, the lookup above will find the
73
+ # _local_ record in the database, which is not what this test is trying
74
+ # to test -- whether we successfully switch models temporarily in a
75
+ # mult-threaded situation. The extra sleep call ensures that the first
76
+ # call completes on both before moving on to the rest of the lookups.
77
+ sleep rand
71
78
  assert_not_nil BespokeTenant.with_remote_model(BespokeModel2.new) {
72
79
  BespokeTenant.find_by_slug(first_slug)
73
80
  sleep rand
@@ -94,7 +101,7 @@ class RemotableTest < ActiveSupport::TestCase
94
101
  :slug => "test-1",
95
102
  :remote_id => nil,
96
103
  :expires_at => 1.day.ago ) }
97
- assert_equal nil, tenant.remote_id
104
+ assert_nil tenant.remote_id
98
105
 
99
106
  # Fetching this tenant, Remotable will want to
100
107
  # refresh it, but it shouldn't because it can't.
@@ -106,11 +113,11 @@ class RemotableTest < ActiveSupport::TestCase
106
113
  :name => "Test 1",
107
114
  :slug => "test-1",
108
115
  :remote_id => nil ) }
109
- assert_equal nil, tenant.remote_id
116
+ assert_nil tenant.remote_id
110
117
 
111
118
  # Updating this tenatn, Remotable will want to
112
119
  # sync it, but it shouldn't because it can't.
113
- assert_equal true, tenant.update_attributes(:name => "Test 2"), "The tenant was not updated (errors: #{tenant.errors.full_messages.join(", ")})"
120
+ assert_equal true, tenant.update(name: "Test 2"), "The tenant was not updated (errors: #{tenant.errors.full_messages.join(", ")})"
114
121
  end
115
122
 
116
123
 
@@ -170,4 +177,17 @@ class RemotableTest < ActiveSupport::TestCase
170
177
  end
171
178
 
172
179
 
180
+
181
+ # ========================================================================= #
182
+ # ActiveRecordExtender #
183
+ # ========================================================================= #
184
+
185
+ test "should extend an ActiveRecord subclass with Nosync class methods" do
186
+ class Example5 < ActiveRecord::Base; self.table_name = "tenants"; end
187
+ Example5.remote_model BespokeModel.new
188
+ # Method is _only_ on the class version
189
+ assert Example5.respond_to?(:unsafe_nosync!)
190
+ end
191
+
192
+
173
193
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: remotable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.3
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Lail
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-20 00:00:00.000000000 Z
11
+ date: 2021-11-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activeresource
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '3.2'
19
+ version: 5.1.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '3.2'
26
+ version: 5.1.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activerecord
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 5.10.3
89
+ version: 5.14.4
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: 5.10.3
96
+ version: 5.14.4
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: minitest-reporters
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -228,19 +228,17 @@ executables: []
228
228
  extensions: []
229
229
  extra_rdoc_files: []
230
230
  files:
231
+ - ".github/workflows/tests.yml"
231
232
  - ".gitignore"
232
233
  - ".simplecov"
233
- - ".travis.yml"
234
234
  - Appraisals
235
235
  - CHANGELOG.md
236
236
  - Gemfile
237
237
  - MIT-LICENSE
238
238
  - README.mdown
239
239
  - Rakefile
240
- - gemfiles/rails_5.0.gemfile
241
- - gemfiles/rails_5.1.gemfile
242
- - gemfiles/rails_5.2.gemfile
243
240
  - gemfiles/rails_6.0.gemfile
241
+ - gemfiles/rails_6.1.gemfile
244
242
  - gemfiles/rails_edge.gemfile
245
243
  - lib/remotable.rb
246
244
  - lib/remotable/active_record_extender.rb
data/.travis.yml DELETED
@@ -1,31 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.3
4
- - 2.5
5
- - 2.6
6
-
7
- gemfile:
8
- - gemfiles/rails_5.0.gemfile
9
- - gemfiles/rails_5.1.gemfile
10
- - gemfiles/rails_5.2.gemfile
11
- - gemfiles/rails_6.0.gemfile
12
- - gemfiles/rails_edge.gemfile
13
-
14
- jobs:
15
- exclude:
16
- - rvm: 2.3
17
- gemfile: gemfiles/rails_6.0.gemfile
18
- - rvm: 2.3
19
- gemfile: gemfiles/rails_edge.gemfile
20
- - rvm: 2.4
21
- gemfile: gemfiles/rails_6.0.gemfile
22
- - rvm: 2.4
23
- gemfile: gemfiles/rails_edge.gemfile
24
- allow_failures:
25
- - gemfile: gemfiles/rails_edge.gemfile
26
-
27
- script: bundle exec rake test
28
-
29
- # To stop Travis from running tests for a new commit,
30
- # add the following to your commit message: [ci skip]
31
- # You should add this when you edit documentation or comments, etc.
@@ -1,8 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "http://rubygems.org"
4
-
5
- gem "activerecord", "~> 5.1.0"
6
- gem "sqlite3", "~> 1.3.6"
7
-
8
- gemspec path: "../"
@@ -1,8 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "http://rubygems.org"
4
-
5
- gem "activerecord", "~> 5.2.0"
6
- gem "sqlite3", "~> 1.3.6"
7
-
8
- gemspec path: "../"