remotable 0.6.3 → 0.9.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.
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: "../"