Remotely lets you specify associations for your models that should be fetched from a remote API instead of the database.
Apps are where Remotely goes to find association resources. You can define as many as you want, but if you define only one, you can omit the :app option from your associations. Remotely also supports any Faraday middleware, to configure just call use_middleware with the class name and options.
Remotely.configure do
app :legsapp do
url "http://somanylegs.com/api/v1"
basic_auth "username", "password"
use_middleware Faraday::HttpCache, store: MyCache.new
end
end
class Millepied < Remotely::Model
app :legsapp
uri "/legs"
# Optional - restrict saveable attributes
attr_savable :name, :type
endhas_many_remote takes two options, :app and :path. :app tells Remotely which registered app to fetch it from. :path tells it the URI to the object (everything after the app).
One app & association name matches URI
class Millepied < ActiveRecord::Base
has_many_remote :legs # => "/legs"
endOne app & custom path
class Millepied < ActiveRecord::Base
has_many_remote :legs, :path => "/store/legs"
endOne app & custom path with id substitution
class Millepied < ActiveRecord::Base
has_many_remote :legs, :path => "/millepieds/:id/legs"
endMultiple apps (all secondary conditions from above apply)
class Millepied < ActiveRecord::Base
has_many_remote :legs, :app => :legsapp, ...
endNote about associations
If you do not specify the :app options in your associations, you need
to create a Remotely::Model subclass for the associated object. This
is so Remotely knows which app to use to retrieve entries of that type.
class Person < ActiveRecord::Base
has_many_remote :legs
end
# Means the following must exist:
class Leg < Remotely::Model
app :legsapp
uri "/legs"
endA path can include ":id" anywhere in it, which is replaced by the instance's id. This is useful when the resource on the API end is namespaced. For example:
class Millepied < ActiveRecord::Base
has_many_remote :legs, :path => "/millepieds/:id/legs"
end
m = Millepied.new
m.id # => 1
m.legs # => Requests "/millepieds/1/legs"Remotely is setup to allow basic auth, token auth, or custom authentication schemes.
Basic Auth
basic_auth accepts 2 String params: username and password
# 'Authorization' header => "Basic dXNlcjpwYXNzd29yZA=="
Remotely.configure do
app :legsapp do
url "http://somanylegs.com/api/v1"
basic_auth "username", "password"
end
endToken Auth
token_auth accepts a String param for the token, and an optional Hash of token options
# 'Authorization' header => "Token token=\"abcdef\", foo=\"bar\""
Remotely.configure do
app :legsapp do
url "http://somanylegs.com/api/v1"
token_auth "abcdef", {:foo => 'bar'}
end
endCustom Authorization
authorization accepts a String param for the type, and either a String or Hash token. A String value is taken literally, and a Hash is encoded into comma separated key/value pairs.
# 'Authorization' header => "Bearer mF_9.B5f-4.1JqM"
Remotely.configure do
app :legsapp do
url "http://somanylegs.com/api/v1"
authorization 'Bearer', 'mF_9.B5f-4.1JqM'
end
end
# 'Authorization' header => "OAuth token=\"abcdef\", foo=\"bar\""
Remotely.configure do
app :legsapp do
url "http://somanylegs.com/api/v1"
authorization 'OAuth', {:token => 'abcdef', :foo => 'bar'}
end
endRemote associations are Remotely::Model objects. Whatever data the API returns, becomes the attributes of the Model.
m = Millepied.new
m.legs[0] # => #<Remotely::Model:0x0000f351c8 @attributes={:length=>"1mm"}>
m.legs[0].length # => "1mm"If a fetched object includes an attribute matching "*_id", Remotely tries to find the model it is for and retrieve it.
leg = m.legs.first
leg.user_id # => 2
leg.user # => User.find(2)Fork, branch and pull-request. Bump versions in their own commit.
