remotable 0.1.1 → 0.1.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 CHANGED
@@ -2,3 +2,5 @@
2
2
  .bundle
3
3
  Gemfile.lock
4
4
  pkg/*
5
+ coverage
6
+
data/.simplecov ADDED
@@ -0,0 +1,3 @@
1
+ SimpleCov.start do
2
+ end
3
+
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Bob Lail
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.mdown ADDED
@@ -0,0 +1,103 @@
1
+ # Remotable
2
+
3
+ Remotable associates an ActiveRecord model with a remote resource (like an ActiveResource model) and keeps the two synchronized.
4
+
5
+ - When a local record is loaded, Remotable ensures that it is up-to-date.
6
+ - When a local record is requested (by an ActiveRecord `find_by_` method) but not found, Remotable fetches the remote resource and creates a local copy.
7
+ - When a local record is created, updated, or destroyed, Remotable ensures that the corresponding remote resource is created, updated, or destroyed.
8
+
9
+ ## Using Remotable
10
+
11
+ ### Installation
12
+
13
+ Just add the following to your Gemfile:
14
+
15
+ gem "remotable"
16
+
17
+ ### Getting Started
18
+
19
+ **1.** Remotable requires that your local model have an `expires_at` column.
20
+
21
+ class AddExpiresAtToTenants < ActiveRecord::Migration
22
+ def self.up
23
+ add_column :tenants, :expires_at, :timestamp, :null => false
24
+ end
25
+ end
26
+
27
+ **2.** Your local model has to be associated with a remote model: (Let's say `RemoteTenant` is the name of an ActiveResource model.)
28
+
29
+ class Tenant < ActiveRecord::Base
30
+ remote_model RemoteTenant
31
+ end
32
+
33
+
34
+ ### Configuration
35
+
36
+ Specify the attributes of the local model that you want to keep in sync with the remote model. You can also specify mappings by using the hash rocket. The line `:customer_name => :name` tells Remotable to keep `RemoteTenant#customer_name` in sync with `Tenant#name`.
37
+
38
+ class Tenant < ActiveRecord::Base
39
+ remote_model RemoteTenant
40
+ attr_remote :slug,
41
+ :customer_name => :name,
42
+ :id => :remote_id
43
+ end
44
+
45
+ By default Remotable assumes that the local model and remote model are joined with the connection you would express in SQL this way: `local_model INNER JOIN remote_model ON local_model.id=remote_model.id`. But it is generally impractical to join on `local_model.id`.
46
+
47
+ If you specify `attr_remote :id => :remote_id`, then the join will be on `local_model.remote_id=remote_model.id`, but you can also use a different attribute as the join key:
48
+
49
+ class Tenant < ActiveRecord::Base
50
+ remote_model RemoteTenant
51
+ attr_remote :slug,
52
+ :customer_name => :name,
53
+ :id => :remote_id
54
+ remote_key :slug
55
+ end
56
+
57
+ Now, the join could be expressed this way: `local_model.slug=remote_model.slug`.
58
+
59
+ ### Finders
60
+
61
+ For all of the local attributes that you've remoted (`slug`, `name`, and `remote_id` in the example above), the remoted model will respond to custom finders (e.g. `find_by_slug`, `find_by_name`, and `find_by_remote_id`). These finders will _first_ look in the local database for the requested record and, if it isn't found, look for the resource remotely. If a finder finds the resource remotely, it creates a local copy and returns that.
62
+
63
+ Without any further configuration, Remotable will assume the route to for the customer finder from the attribute. For example,
64
+
65
+ find_by_id(...) # Looks in api_path/tenants/:id
66
+ find_by_slug(...) # Looks in api_path/tenants/by_slug/:slug
67
+ find_by_customer_name(...) # Looks in api_path/tenants/by_customer_name/:customer_name
68
+
69
+ You can specify a custom path with the `find_by` method or you can always write an appropriate `find_by_whatever` method on your remote resource.
70
+
71
+ class Tenant < ActiveRecord::Base
72
+ remote_model RemoteTenant
73
+ attr_remote :slug,
74
+ :customer_name => :name,
75
+ :id => :remote_id
76
+ find_by :name, :path => "by_nombre/:name"
77
+ end
78
+
79
+ When you use `find_by`, give the name of the _local_ attribute not the remote one (if they differ). Also, the name of the symbolic part of the path should match the local attribute name as well.
80
+
81
+ ### Expiration
82
+
83
+ Whenever a remoted record is instantiated, Remotable checks the value of its `expires_at` attribute. If the date is in the past, Remotable pulls changes from the remote resource. Whenever a record is saved, `expires_at` is set to a time in the future&mdash;by default, 1 day. You can change how frequently a record expires by setting `expires_after` to a duration:
84
+
85
+ class Tenant < ActiveRecord::Base
86
+ remote_model RemoteTenant
87
+ expires_after 1.hour
88
+ end
89
+
90
+ ### Adapters
91
+
92
+ Remotable checks class you hand to `remote_model` to see what it inherits from. Remotable checks this to use the correct adapter with the remote model. Currently, the only adapter included in Remotable is for ActiveResource::Base.
93
+
94
+ ## Development
95
+
96
+ ### To Do
97
+
98
+ - Add additional adapters
99
+ - Write a generator
100
+
101
+ ### License
102
+
103
+ Remotable is available under the terms of the MIT license.
data/lib/remotable.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require "remotable/version"
2
+ require "remotable/nosync"
2
3
 
3
4
 
4
5
  # Remotable keeps a locally-stored ActiveRecord
@@ -28,6 +29,7 @@ require "remotable/version"
28
29
  #
29
30
  #
30
31
  module Remotable
32
+ extend Nosync
31
33
 
32
34
 
33
35
 
@@ -5,6 +5,11 @@ require "active_support/concern"
5
5
  module Remotable
6
6
  module ActiveRecordExtender
7
7
  extend ActiveSupport::Concern
8
+ include Nosync
9
+
10
+ def nosync?
11
+ self.class.nosync? || super
12
+ end
8
13
 
9
14
 
10
15
 
@@ -28,6 +33,11 @@ module Remotable
28
33
 
29
34
 
30
35
  module ClassMethods
36
+ include Nosync
37
+
38
+ def nosync?
39
+ Remotable.nosync? || super
40
+ end
31
41
 
32
42
  def remote_key(*args)
33
43
  if args.any?
@@ -51,13 +61,16 @@ module Remotable
51
61
 
52
62
  def attr_remote(*attrs)
53
63
  map = attrs.extract_options!
54
- map = attrs.map_to_self(map)
64
+ map = attrs.map_to_self.merge(map)
55
65
  @remote_attribute_map = map
66
+
67
+ @remote_attribute_routes = {}
68
+ fetch_with(*local_attribute_names)
56
69
  end
57
70
 
58
- def fetch_with(*args)
59
- keys_and_routes = extract_keys_and_routes(*args)
60
- @remote_attribute_routes.merge!(keys_and_routes)
71
+ def fetch_with(*local_keys)
72
+ remote_keys_and_routes = extract_remote_keys_and_routes(*local_keys)
73
+ @remote_attribute_routes.merge!(remote_keys_and_routes)
61
74
  end
62
75
  alias :find_by :fetch_with
63
76
 
@@ -93,7 +106,11 @@ module Remotable
93
106
 
94
107
  def default_route_for(local_key, remote_key=nil)
95
108
  remote_key ||= remote_attribute_name(local_key)
96
- "by_#{remote_key}/:#{local_key}.json"
109
+ if remote_key.to_s == primary_key
110
+ ":#{local_key}"
111
+ else
112
+ "by_#{remote_key}/:#{local_key}"
113
+ end
97
114
  end
98
115
 
99
116
 
@@ -102,8 +119,10 @@ module Remotable
102
119
  # so you can use the remoted record in associations.
103
120
  def instantiate(*args)
104
121
  record = super
105
- record.pull_remote_data! if record.expired?
106
- record = nil if record.destroyed?
122
+ if record.expired? && !Remotable.nosync?
123
+ record.pull_remote_data!
124
+ record = nil if record.destroyed?
125
+ end
107
126
  record
108
127
  end
109
128
 
@@ -112,7 +131,7 @@ module Remotable
112
131
  def method_missing(method_sym, *args, &block)
113
132
  method_name = method_sym.to_s
114
133
 
115
- if method_name =~ /find_by_(.*)(!?)/
134
+ if method_name =~ /find_by_([^!]*)(!?)/
116
135
  local_attr, bang, value = $1.to_sym, !$2.blank?, args.first
117
136
  remote_attr = remote_attribute_name(local_attr)
118
137
 
@@ -120,11 +139,8 @@ module Remotable
120
139
  # primary key if we're evaluating a finder
121
140
 
122
141
  if remote_attribute_routes.key?(remote_attr)
123
- local_resource = where(local_attr => value).first
124
- unless local_resource
125
- remote_resource = remote_model.find_by(remote_attr, value)
126
- local_resource = new_from_remote(remote_resource) if remote_resource
127
- end
142
+ local_resource = where(local_attr => value).first ||
143
+ fetch_by(remote_attr, value)
128
144
 
129
145
  raise ActiveRecord::RecordNotFound if local_resource.nil? && bang
130
146
  return local_resource
@@ -136,6 +152,22 @@ module Remotable
136
152
 
137
153
 
138
154
 
155
+ def expire_all!
156
+ update_all(["expires_at=?", 1.day.ago])
157
+ end
158
+
159
+
160
+
161
+ # Looks the resource up remotely, by the given attribute
162
+ # If the resource is found, wraps it in a new local resource
163
+ # and returns that.
164
+ def fetch_by(remote_attr, value)
165
+ remote_resource = remote_model.find_by(remote_attr, value)
166
+ remote_resource && new_from_remote(remote_resource)
167
+ end
168
+
169
+
170
+
139
171
  private
140
172
 
141
173
 
@@ -156,7 +188,7 @@ module Remotable
156
188
  end
157
189
 
158
190
 
159
- def extract_keys_and_routes(*local_keys)
191
+ def extract_remote_keys_and_routes(*local_keys)
160
192
  keys_and_routes = local_keys.extract_options!
161
193
  {}.tap do |hash|
162
194
  local_keys.each {|local_key| hash[remote_attribute_name(local_key)] = nil}
@@ -220,28 +252,6 @@ module Remotable
220
252
 
221
253
 
222
254
 
223
- def nosync!
224
- @nosync = true
225
- end
226
-
227
- def nosync
228
- value = @nosync
229
- @nosync = true
230
- yield
231
- ensure
232
- @nosync = value
233
- end
234
-
235
- def nosync=(val)
236
- @nosync = (val == true)
237
- end
238
-
239
- def nosync?
240
- @nosync == true
241
- end
242
-
243
-
244
-
245
255
  private
246
256
 
247
257
  def fetch_remote_resource
@@ -1,4 +1,5 @@
1
1
  require "remotable/active_resource_fixes"
2
+ require "remotable/core_ext/uri"
2
3
  require "active_support/concern"
3
4
 
4
5
 
@@ -19,11 +20,7 @@ module Remotable
19
20
 
20
21
 
21
22
  def find_by!(key, value)
22
- if key == :id
23
- find(value)
24
- else
25
- find(:one, :from => path_for(key, value))
26
- end
23
+ find(:one, :from => path_for(key, value))
27
24
  end
28
25
 
29
26
  def find_by(key, value)
@@ -39,9 +36,9 @@ module Remotable
39
36
  route = route_for(local_key)
40
37
  path = route.gsub(/:#{local_key}/, value.to_s)
41
38
  if relative_path?(path)
42
- path
39
+ URI.join_url_segments(prefix, collection_name, "#{path}.#{format.extension}")
43
40
  else
44
- join_url_segments(prefix, collection_name, path)
41
+ path
45
42
  end
46
43
  end
47
44
 
@@ -52,11 +49,7 @@ module Remotable
52
49
 
53
50
 
54
51
  def relative_path?(path)
55
- path.start_with?("/") || path["://"]
56
- end
57
-
58
- def join_url_segments(*segments)
59
- segments.flatten.join("/").gsub(/\/+/, "/")
52
+ !(path.start_with?("/") || path["://"])
60
53
  end
61
54
 
62
55
 
@@ -0,0 +1,22 @@
1
+ require "uri"
2
+
3
+
4
+ module Remotable
5
+ module CoreExt
6
+ module URI
7
+
8
+
9
+ def join_url_segments(*segments)
10
+ segments = segments.dup.flatten.map(&:to_s)
11
+ first_segment = segments.shift.gsub(/\/$/, "")
12
+ segments.map! { |seg| seg.gsub(/(^\/)|(\/$)/, "") }
13
+ [first_segment, *segments].join("/")
14
+ end
15
+
16
+
17
+ end
18
+ end
19
+ end
20
+
21
+
22
+ ::URI.extend(Remotable::CoreExt::URI)
@@ -0,0 +1,28 @@
1
+
2
+ module Remotable
3
+ module Nosync
4
+
5
+
6
+ def nosync!
7
+ self.nosync = true
8
+ end
9
+
10
+ def nosync
11
+ value = @nosync
12
+ nosync!
13
+ yield
14
+ ensure
15
+ self.nosync = value
16
+ end
17
+
18
+ def nosync=(val)
19
+ @nosync = (val == true)
20
+ end
21
+
22
+ def nosync?
23
+ @nosync == true
24
+ end
25
+
26
+
27
+ end
28
+ end
@@ -1,3 +1,3 @@
1
1
  module Remotable
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
data/remotable.gemspec CHANGED
@@ -22,6 +22,7 @@ Gem::Specification.new do |s|
22
22
  s.add_development_dependency "factory_girl"
23
23
  s.add_development_dependency "sqlite3"
24
24
  s.add_development_dependency "active_resource_simulator"
25
+ s.add_development_dependency "simplecov"
25
26
 
26
27
  s.files = `git ls-files`.split("\n")
27
28
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -0,0 +1,30 @@
1
+ require "test_helper"
2
+ require "remotable"
3
+ require "support/active_resource"
4
+
5
+
6
+ class NoSyncTest < ActiveSupport::TestCase
7
+
8
+
9
+
10
+ test "nosync? should be false by default" do
11
+ assert_equal false, Tenant.new.nosync?
12
+ end
13
+
14
+ test "nosync? should be true if remotable is turned off globally" do
15
+ Remotable.nosync do
16
+ assert_equal true, Tenant.new.nosync?
17
+ assert_equal true, RemoteWithoutKey.new.nosync?
18
+ end
19
+ end
20
+
21
+ test "nosync? should be true if remotable is turned off for the model" do
22
+ Tenant.nosync do
23
+ assert_equal true, Tenant.new.nosync?
24
+ assert_equal false, RemoteWithoutKey.new.nosync?
25
+ end
26
+ end
27
+
28
+
29
+
30
+ end
@@ -45,6 +45,43 @@ class RemotableTest < ActiveSupport::TestCase
45
45
  end
46
46
  end
47
47
 
48
+ test "should be able to find resources with the bang method" do
49
+ new_tenant_slug = "not_found2"
50
+
51
+ assert_equal 0, Tenant.where(:slug => new_tenant_slug).count,
52
+ "There's not supposed to be a Tenant with the slug #{new_tenant_slug}."
53
+
54
+ assert_difference "Tenant.count", +1 do
55
+ RemoteTenant.run_simulation do |s|
56
+ s.show(nil, {
57
+ :id => 46,
58
+ :slug => new_tenant_slug,
59
+ :church_name => "Not Found"
60
+ }, :path => "/api/accounts/by_slug/#{new_tenant_slug}.json")
61
+
62
+ new_tenant = Tenant.find_by_slug!(new_tenant_slug)
63
+ assert_not_nil new_tenant, "A remote tenant was not found with the slug #{new_tenant_slug.inspect}"
64
+ end
65
+ end
66
+ end
67
+
68
+ test "if a resource is neither local nor remote, raise an exception with the bang method" do
69
+ new_tenant_slug = "not_found3"
70
+
71
+ assert_equal 0, Tenant.where(:slug => new_tenant_slug).count,
72
+ "There's not supposed to be a Tenant with the slug #{new_tenant_slug}."
73
+
74
+ RemoteTenant.run_simulation do |s|
75
+ s.show(nil, nil, :status => 404, :path => "/api/accounts/by_slug/#{new_tenant_slug}.json")
76
+
77
+ assert_raises ActiveRecord::RecordNotFound do
78
+ Tenant.find_by_slug!(new_tenant_slug)
79
+ end
80
+ end
81
+ end
82
+
83
+
84
+
48
85
  test "should be able to find resources by different attributes and specify a path" do
49
86
  new_tenant_name = "JohnnyG"
50
87
 
@@ -14,8 +14,7 @@ end
14
14
  class Tenant < ActiveRecord::Base
15
15
  remote_model RemoteTenant
16
16
  attr_remote :slug, :church_name => :name, :id => :remote_id
17
- find_by :slug
18
- find_by :name => "by_nombre/:name.json"
17
+ find_by :name => "by_nombre/:name"
19
18
  end
20
19
 
21
20
 
data/test/test_helper.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'rubygems'
2
+ require 'simplecov'
2
3
  require 'rails'
3
4
  require 'rails/test_help'
4
5
  require 'active_support/core_ext'
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: remotable
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.1.1
5
+ version: 0.1.2
6
6
  platform: ruby
7
7
  authors:
8
8
  - Robert Lail
@@ -10,12 +10,11 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-08-26 00:00:00 -05:00
13
+ date: 2011-09-19 00:00:00 -05:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: activeresource
18
- prerelease: false
19
18
  requirement: &id001 !ruby/object:Gem::Requirement
20
19
  none: false
21
20
  requirements:
@@ -23,10 +22,10 @@ dependencies:
23
22
  - !ruby/object:Gem::Version
24
23
  version: "0"
25
24
  type: :runtime
25
+ prerelease: false
26
26
  version_requirements: *id001
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activerecord
29
- prerelease: false
30
29
  requirement: &id002 !ruby/object:Gem::Requirement
31
30
  none: false
32
31
  requirements:
@@ -34,10 +33,10 @@ dependencies:
34
33
  - !ruby/object:Gem::Version
35
34
  version: "0"
36
35
  type: :runtime
36
+ prerelease: false
37
37
  version_requirements: *id002
38
38
  - !ruby/object:Gem::Dependency
39
39
  name: activesupport
40
- prerelease: false
41
40
  requirement: &id003 !ruby/object:Gem::Requirement
42
41
  none: false
43
42
  requirements:
@@ -45,10 +44,10 @@ dependencies:
45
44
  - !ruby/object:Gem::Version
46
45
  version: "0"
47
46
  type: :runtime
47
+ prerelease: false
48
48
  version_requirements: *id003
49
49
  - !ruby/object:Gem::Dependency
50
50
  name: rails
51
- prerelease: false
52
51
  requirement: &id004 !ruby/object:Gem::Requirement
53
52
  none: false
54
53
  requirements:
@@ -56,10 +55,10 @@ dependencies:
56
55
  - !ruby/object:Gem::Version
57
56
  version: "0"
58
57
  type: :development
58
+ prerelease: false
59
59
  version_requirements: *id004
60
60
  - !ruby/object:Gem::Dependency
61
61
  name: turn
62
- prerelease: false
63
62
  requirement: &id005 !ruby/object:Gem::Requirement
64
63
  none: false
65
64
  requirements:
@@ -67,10 +66,10 @@ dependencies:
67
66
  - !ruby/object:Gem::Version
68
67
  version: "0"
69
68
  type: :development
69
+ prerelease: false
70
70
  version_requirements: *id005
71
71
  - !ruby/object:Gem::Dependency
72
72
  name: factory_girl
73
- prerelease: false
74
73
  requirement: &id006 !ruby/object:Gem::Requirement
75
74
  none: false
76
75
  requirements:
@@ -78,10 +77,10 @@ dependencies:
78
77
  - !ruby/object:Gem::Version
79
78
  version: "0"
80
79
  type: :development
80
+ prerelease: false
81
81
  version_requirements: *id006
82
82
  - !ruby/object:Gem::Dependency
83
83
  name: sqlite3
84
- prerelease: false
85
84
  requirement: &id007 !ruby/object:Gem::Requirement
86
85
  none: false
87
86
  requirements:
@@ -89,10 +88,10 @@ dependencies:
89
88
  - !ruby/object:Gem::Version
90
89
  version: "0"
91
90
  type: :development
91
+ prerelease: false
92
92
  version_requirements: *id007
93
93
  - !ruby/object:Gem::Dependency
94
94
  name: active_resource_simulator
95
- prerelease: false
96
95
  requirement: &id008 !ruby/object:Gem::Requirement
97
96
  none: false
98
97
  requirements:
@@ -100,7 +99,19 @@ dependencies:
100
99
  - !ruby/object:Gem::Version
101
100
  version: "0"
102
101
  type: :development
102
+ prerelease: false
103
103
  version_requirements: *id008
104
+ - !ruby/object:Gem::Dependency
105
+ name: simplecov
106
+ requirement: &id009 !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: "0"
112
+ type: :development
113
+ prerelease: false
114
+ version_requirements: *id009
104
115
  description: Remotable keeps a locally-stored ActiveRecord synchronized with a remote resource.
105
116
  email:
106
117
  - robert.lail@cph.org
@@ -112,7 +123,10 @@ extra_rdoc_files: []
112
123
 
113
124
  files:
114
125
  - .gitignore
126
+ - .simplecov
115
127
  - Gemfile
128
+ - MIT-LICENSE
129
+ - README.mdown
116
130
  - Rakefile
117
131
  - lib/remotable.rb
118
132
  - lib/remotable/active_record_extender.rb
@@ -120,9 +134,12 @@ files:
120
134
  - lib/remotable/adapters/active_resource.rb
121
135
  - lib/remotable/core_ext.rb
122
136
  - lib/remotable/core_ext/enumerable.rb
137
+ - lib/remotable/core_ext/uri.rb
138
+ - lib/remotable/nosync.rb
123
139
  - lib/remotable/version.rb
124
140
  - remotable.gemspec
125
141
  - test/factories/tenants.rb
142
+ - test/nosync_test.rb
126
143
  - test/remotable_test.rb
127
144
  - test/support/active_resource.rb
128
145
  - test/support/schema.rb
@@ -141,12 +158,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
141
158
  requirements:
142
159
  - - ">="
143
160
  - !ruby/object:Gem::Version
161
+ hash: -3964453781744969533
162
+ segments:
163
+ - 0
144
164
  version: "0"
145
165
  required_rubygems_version: !ruby/object:Gem::Requirement
146
166
  none: false
147
167
  requirements:
148
168
  - - ">="
149
169
  - !ruby/object:Gem::Version
170
+ hash: -3964453781744969533
171
+ segments:
172
+ - 0
150
173
  version: "0"
151
174
  requirements: []
152
175
 
@@ -157,6 +180,7 @@ specification_version: 3
157
180
  summary: Binds an ActiveRecord model to a remote resource and keeps the two synchronized
158
181
  test_files:
159
182
  - test/factories/tenants.rb
183
+ - test/nosync_test.rb
160
184
  - test/remotable_test.rb
161
185
  - test/support/active_resource.rb
162
186
  - test/support/schema.rb