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 +2 -0
- data/.simplecov +3 -0
- data/MIT-LICENSE +20 -0
- data/README.mdown +103 -0
- data/lib/remotable.rb +2 -0
- data/lib/remotable/active_record_extender.rb +46 -36
- data/lib/remotable/adapters/active_resource.rb +5 -12
- data/lib/remotable/core_ext/uri.rb +22 -0
- data/lib/remotable/nosync.rb +28 -0
- data/lib/remotable/version.rb +1 -1
- data/remotable.gemspec +1 -0
- data/test/nosync_test.rb +30 -0
- data/test/remotable_test.rb +37 -0
- data/test/support/active_resource.rb +1 -2
- data/test/test_helper.rb +1 -0
- metadata +34 -10
data/.simplecov
ADDED
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—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
@@ -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(*
|
59
|
-
|
60
|
-
@remote_attribute_routes.merge!(
|
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
|
-
|
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
|
-
|
106
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
data/lib/remotable/version.rb
CHANGED
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")
|
data/test/nosync_test.rb
ADDED
@@ -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
|
data/test/remotable_test.rb
CHANGED
@@ -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
|
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: remotable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.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-
|
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
|