Spyke alternatives and similar gems
Based on the "HTTP" category.
Alternatively, view Spyke alternatives based on common mentions on social networks and blogs.
-
Faraday
Simple, but flexible HTTP client library, with support for multiple backends. -
RESTClient
Simple HTTP and REST client for Ruby, inspired by microframework syntax for specifying actions. -
Typhoeus
Typhoeus wraps libcurl in order to make fast and reliable requests. -
HTTP
HTTP (The Gem! a.k.a. http.rb) - a fast Ruby HTTP client with a chainable API, streaming support, and timeouts -
Http Client
'httpclient' gives something like the functionality of libwww-perl (LWP) in Ruby. -
Net
Net::HTTP provides a rich library which can be used to build HTTP user-agents. -
Accept Language
Ruby parser for Accept-Language request HTTP header ๐
Access the most powerful time series database as a service
* Code Quality Rankings and insights are calculated and provided by Lumnify.
They vary from L1 to L5 with "L5" being the highest.
Do you think we are missing an alternative of Spyke or a related project?
Popular Comparisons
README
Spyke
Interact with remote REST services in an ActiveRecord-like manner.
Spyke basically rips off takes inspiration :innocent: from Her, a gem which we sadly had to abandon as it gave us some performance problems and maintenance seemed to have gone stale.
We therefore made Spyke which adds a few fixes/features needed for our projects:
- Fast handling of even large amounts of JSON
- Proper support for scopes
- Ability to define custom URIs for associations
- ActiveRecord-like log output
- Handling of API-side validations
- Googlable name! :)
Configuration
Add this line to your application's Gemfile:
gem 'spyke'
gem 'multi_json' # or whatever is needed to parse responses
Spyke uses Faraday to handle requests and expects it to parse the response body into a hash in the following format:
{ data: { id: 1, name: 'Bob' }, metadata: {}, errors: {} }
So, for example for an API that returns JSON like this:
{ "result": { "id": 1, "name": "Bob" }, "extra": {}, "errors": {} }
...the simplest possible configuration that could work is something like this:
# config/initializers/spyke.rb
class JSONParser < Faraday::Response::Middleware
def parse(body)
json = MultiJson.load(body, symbolize_keys: true)
{
data: json[:result],
metadata: json[:extra],
errors: json[:errors]
}
end
end
Spyke::Base.connection = Faraday.new(url: 'http://api.com') do |c|
c.request :json
c.use JSONParser
c.adapter Faraday.default_adapter
end
Usage
Adding a class and inheriting from Spyke::Base
will allow you to interact with the remote service:
class User < Spyke::Base
has_many :posts
scope :active, -> { where(active: true) }
end
User.all
# => GET http://api.com/users
User.active
# => GET http://api.com/users?active=true
User.where(age: 3).active
# => GET http://api.com/users?active=true&age=3
user = User.find(3)
# => GET http://api.com/users/3
user.posts
# => find embedded in returned data or GET http://api.com/users/3/posts
user.update(name: 'Alice')
# => PUT http://api.com/users/3 - { user: { name: 'Alice' } }
user.destroy
# => DELETE http://api.com/users/3
User.create(name: 'Bob')
# => POST http://api.com/users - { user: { name: 'Bob' } }
Custom URIs
You can specify custom URIs on both the class and association level.
Set uri to nil
for associations you only want to use data embedded
in the response and never call out to the API.
class User < Spyke::Base
uri 'people(/:id)' # id optional, both /people and /people/4 are valid
has_many :posts, uri: 'posts/for_user/:user_id' # user_id is required
has_one :image, uri: nil # only use embedded data
end
class Post < Spyke::Base
end
user = User.find(3) # => GET http://api.com/people/3
user.image # Will only use embedded data and never call out to api
user.posts # => GET http://api.com/posts/for_user/3
Post.find(4) # => GET http://api.com/posts/4
Custom requests
Custom request methods and the with
scope methods allow you to
perform requests for non-REST actions:
The .with
scope:
Post.with('posts/recent') # => GET http://api.com/posts/recent
Post.with(:recent) # => GET http://api.com/posts/recent
Post.with(:recent).where(status: 'draft') # => GET http://api.com/posts/recent?status=draft
Post.with(:recent).post # => POST http://api.com/posts/recent
Custom requests from instance:
Post.find(3).put(:publish) # => PUT http://api.com/posts/3/publish
Arbitrary requests (returns plain Result object):
Post.request(:post, 'posts/3/log', time: '12:00')
# => POST http://api.com/posts/3/log - { time: '12:00' }
Custom primary keys
Custom primary keys can be defined with self.primary_key = :custom_key
:
class User < Spyke::Base
self.primary_key = :user_id
# When using custom URIs the :id parameter also has to be adjusted
uri 'people(/:user_id)'
end
API-side validations
Spyke expects errors to be formatted in the same way as the ActiveModel::Errors details hash, ie:
{ title: [{ error: 'blank'}, { error: 'too_short', count: 10 }]}
If the API you're using returns errors in a different format you can
remap it in Faraday to match the above. Doing this will allow you to
show errors returned from the server in forms and f.ex using
@post.errors.full_messages
just like ActiveRecord.
Error handling and fallbacks
Should the API fail to connect or time out, a Spyke::ConnectionError
will be raised.
If you need to recover gracefully from connection problems, you can
either rescue that exception or use the with_fallback
feature:
# API is down
Article.all # => Spyke::ConnectionError
Article.with_fallback.all # => []
Article.find(1) # => Spyke::ConnectionError
Article.with_fallback.find(1) # => nil
article = Article.with_fallback(Article.new(title: "Dummy")).find(1)
article.title # => "Dummy"
Attributes-wrapping
Spyke, like Rails, by default wraps sent attributes in a root element, but this can be disabled or customized:
class Article < Spyke::Base
# Default
include_root_in_json true # { article: { title: ...} }
# Custom
include_root_in_json :post # { post: { title: ...} }
# Disabled
include_root_in_json false # { title: ... }
end
Using multiple APIs
If you need to use different APIs, instead of configuring Spyke::Base
you can configure each class individually:
class Post < Spyke::Base
self.connection = Faraday.new(url: 'http://sashimi.com') do |faraday|
# middleware
end
end
Log output
When used with Rails, Spyke will automatically output helpful ActiveRecord-like messages to the main log:
Started GET "/posts" for 127.0.0.1 at 2014-12-01 14:31:20 +0000
Processing by PostsController#index as HTML
Parameters: {}
Spyke (40.3ms) GET http://api.com/posts [200]
Completed 200 OK in 75ms (Views: 64.6ms | Spyke: 40.3ms | ActiveRecord: 0ms)
Other examples
For more examples of how Spyke can be used, check out fixtures.rb and the test suite.
Contributing
If possible please take a look at the tests marked "wishlisted"! These are features/fixes I'd like to implement but haven't gotten around to doing yet :)