Skip to content

Commit

Permalink
rename and add docs
Browse files Browse the repository at this point in the history
  • Loading branch information
balvig committed Nov 17, 2014
1 parent dec1a36 commit 4f42f8c
Show file tree
Hide file tree
Showing 34 changed files with 143 additions and 88 deletions.
2 changes: 1 addition & 1 deletion Gemfile
@@ -1,4 +1,4 @@
source 'https://rubygems.org'

# Specify your gem's dependencies in spike.gemspec
# Specify your gem's dependencies in spyke.gemspec
gemspec
83 changes: 69 additions & 14 deletions README.md
@@ -1,29 +1,84 @@
# Spike
# Spyke

TODO: Write a gem description
Spyke allows you to interact with remote REST services in an ActiveRecord-like manner.

## Installation
It basically ~~rips off~~ takes inspiration from :innocent: [Her](https://github.com/remiprev/her), a gem which we sadly had to abandon as it showed significant performance problems and maintenance seemed to had gone stale.

We therefore made Spyke which adds a few fixes/features that we needed for our projects:

- Fast handling of even large amounts of JSON
- Proper support for scopes
- Ability to define custom URIs for associations
- Googlable name! :)

## Configuration

Add this line to your application's Gemfile:

gem 'spike'
gem 'spyke'

And then execute:
Like Her, Spyke uses Faraday to handle requests and expects a hash in the following format:

$ bundle
```ruby
{ result: { id: 1, name: 'Bob' }, metadata: {} }
```

Or install it yourself as:
The simplest possible configuration that can work is something like this:

$ gem install spike
```ruby
# config/initializers/spyke.rb

class JSONParser < Faraday::Response::Middleware
def parse(body)
json = MultiJson.load(body, symbolize_keys: true)
{
data: json[:result],
metadata: json[:metadata]
}
end
end

Spyke::Config.connection = Faraday.new(url: 'http://api.com') do |c|
c.use JSONParser
c.use Faraday::Adapter::NetHttp
end
```

## Usage

TODO: Write usage instructions here
Adding a class and inheriting from `Spyke::Base` will allow you to interact with the remote service:

```ruby
class User < Spyke::Base
has_many :posts
end

user = User.find(3) # => GET http://api.com/users/3
user.posts # => find embedded in user or GET http://api.com/users/3/posts
```

### Custom URIs

You can specify custom URIs on both the class and association level:

```ruby
class User < Spyke::Base
uri '/v1/users/:id'

has_one :image, uri: nil
has_many :posts, uri: '/posts/for_user/:user_id'
end

class Post < Spyke::Base
end

user = User.find(3) # => GET http://api.com/v1/users/3
user.image # Will only use embedded JSON 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
```

## Contributing

1. Fork it ( https://github.com/[my-github-username]/spike/fork )
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create a new Pull Request
If possible please take a look at the tests marked "wishlisted"!
These are features/fixes we want to implement but haven't gotten around to doing yet :)
6 changes: 0 additions & 6 deletions lib/spike.rb

This file was deleted.

3 changes: 0 additions & 3 deletions lib/spike/version.rb

This file was deleted.

6 changes: 6 additions & 0 deletions lib/spyke.rb
@@ -0,0 +1,6 @@
require 'active_support/core_ext'
require 'spyke/base'
require 'spyke/version'

module Spyke
end
10 changes: 5 additions & 5 deletions lib/spike/associations.rb → lib/spyke/associations.rb
@@ -1,9 +1,9 @@
require 'spike/associations/association'
require 'spike/associations/has_many'
require 'spike/associations/has_one'
require 'spike/associations/belongs_to'
require 'spyke/associations/association'
require 'spyke/associations/has_many'
require 'spyke/associations/has_one'
require 'spyke/associations/belongs_to'

module Spike
module Spyke
module Associations
extend ActiveSupport::Concern

Expand Down
@@ -1,7 +1,7 @@
require 'spike/relation'
require 'spike/result'
require 'spyke/relation'
require 'spyke/result'

module Spike
module Spyke
module Associations
class Association < Relation
attr_reader :parent, :name
Expand Down
@@ -1,4 +1,4 @@
module Spike
module Spyke
module Associations
class BelongsTo < Association
def initialize(*args)
Expand Down
@@ -1,4 +1,4 @@
module Spike
module Spyke
module Associations
class HasMany < Association
def initialize(*args)
Expand Down
@@ -1,4 +1,4 @@
module Spike
module Spyke
module Associations
class HasOne < Association
def initialize(*args)
Expand Down
8 changes: 4 additions & 4 deletions lib/spike/attributes.rb → lib/spyke/attributes.rb
@@ -1,6 +1,6 @@
require 'spike/collection'
require 'spyke/collection'

module Spike
module Spyke
module Attributes
extend ActiveSupport::Concern

Expand Down Expand Up @@ -37,7 +37,7 @@ def id=(value)
end

def ==(other)
other.is_a?(Spike::Base) && id == other.id
other.is_a?(Spyke::Base) && id == other.id
end

def inspect
Expand All @@ -58,7 +58,7 @@ def parse(attributes)

def parse_value(value)
case
when value.is_a?(Spike::Base) then parse(value.attributes)
when value.is_a?(Spyke::Base) then parse(value.attributes)
when value.is_a?(Hash) then parse(value)
when value.is_a?(Array) then value.map { |v| parse_value(v) }
when value.respond_to?(:content_type) then Faraday::UploadIO.new(value.path, value.content_type)
Expand Down
14 changes: 7 additions & 7 deletions lib/spike/base.rb → lib/spyke/base.rb
@@ -1,11 +1,11 @@
require 'active_model'
require 'spike/associations'
require 'spike/attributes'
require 'spike/orm'
require 'spike/http'
require 'spike/scopes'
require 'spyke/associations'
require 'spyke/attributes'
require 'spyke/orm'
require 'spyke/http'
require 'spyke/scopes'

module Spike
module Spyke
class Base
# ActiveModel
include ActiveModel::Conversion
Expand All @@ -15,7 +15,7 @@ class Base
extend ActiveModel::Translation
extend ActiveModel::Callbacks

# Spike
# Spyke
include Associations
include Attributes
include Http
Expand Down
2 changes: 1 addition & 1 deletion lib/spike/collection.rb → lib/spyke/collection.rb
@@ -1,4 +1,4 @@
module Spike
module Spyke
class Collection < ::Array
attr_reader :metadata

Expand Down
2 changes: 1 addition & 1 deletion lib/spike/config.rb → lib/spyke/config.rb
@@ -1,4 +1,4 @@
module Spike
module Spyke
class Config
class_attribute :connection
end
Expand Down
2 changes: 1 addition & 1 deletion lib/spike/exceptions.rb → lib/spyke/exceptions.rb
@@ -1,3 +1,3 @@
module Spike
module Spyke
class ResourceNotFound < StandardError; end
end
8 changes: 4 additions & 4 deletions lib/spike/http.rb → lib/spyke/http.rb
@@ -1,9 +1,9 @@
require 'faraday'
require 'spike/config'
require 'spike/path'
require 'spike/result'
require 'spyke/config'
require 'spyke/path'
require 'spyke/result'

module Spike
module Spyke
module Http
extend ActiveSupport::Concern
METHODS = %i{ get post put patch delete }
Expand Down
2 changes: 1 addition & 1 deletion lib/spike/orm.rb → lib/spyke/orm.rb
@@ -1,4 +1,4 @@
module Spike
module Spyke
module Orm
extend ActiveSupport::Concern

Expand Down
2 changes: 1 addition & 1 deletion lib/spike/path.rb → lib/spyke/path.rb
@@ -1,6 +1,6 @@
require 'uri_template'

module Spike
module Spyke
class Path
def initialize(uri_template, params = {})
@uri_template = URITemplate.new(:colon, uri_template)
Expand Down
4 changes: 2 additions & 2 deletions lib/spike/relation.rb → lib/spyke/relation.rb
@@ -1,6 +1,6 @@
require 'spike/exceptions'
require 'spyke/exceptions'

module Spike
module Spyke
class Relation
include Enumerable

Expand Down
2 changes: 1 addition & 1 deletion lib/spike/result.rb → lib/spyke/result.rb
@@ -1,4 +1,4 @@
module Spike
module Spyke
class Result
attr_reader :body

Expand Down
@@ -1,4 +1,4 @@
module Spike
module Spyke
class ScopeRegistry
extend ActiveSupport::PerThreadRegistry

Expand Down
6 changes: 3 additions & 3 deletions lib/spike/scopes.rb → lib/spyke/scopes.rb
@@ -1,7 +1,7 @@
require 'spike/relation'
require 'spike/scope_registry'
require 'spyke/relation'
require 'spyke/scope_registry'

module Spike
module Spyke
module Scopes
extend ActiveSupport::Concern

Expand Down
3 changes: 3 additions & 0 deletions lib/spyke/version.rb
@@ -0,0 +1,3 @@
module Spyke
VERSION = '1.0.0'
end
20 changes: 10 additions & 10 deletions spike.gemspec → spyke.gemspec
@@ -1,15 +1,15 @@
# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'spike/version'
require 'spyke/version'

Gem::Specification.new do |spec|
spec.name = "spike"
spec.version = Spike::VERSION
spec.name = "spyke"
spec.version = Spyke::VERSION
spec.authors = ["Jens Balvig"]
spec.email = ["jens@balvig.com"]
spec.summary = %q{Faster version of Her}
spec.description = %q{Faster version of Her}
spec.summary = %q{Interact with REST services in an ActiveRecord-like manner}
spec.description = %q{Interact with REST services in an ActiveRecord-like manner}
spec.homepage = ""
spec.license = "MIT"

Expand All @@ -18,6 +18,11 @@ Gem::Specification.new do |spec|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ["lib"]

spec.add_dependency "activesupport"
spec.add_dependency "activemodel"
spec.add_dependency "faraday"
spec.add_dependency "uri_template"

spec.add_development_dependency "bundler", "~> 1.6"
spec.add_development_dependency "faraday_middleware"
spec.add_development_dependency "minitest"
Expand All @@ -28,9 +33,4 @@ Gem::Specification.new do |spec|
spec.add_development_dependency "pry"
spec.add_development_dependency "rake"
spec.add_development_dependency "webmock"

spec.add_dependency "activesupport"
spec.add_dependency "activemodel"
spec.add_dependency "faraday"
spec.add_dependency "uri_template"
end
2 changes: 1 addition & 1 deletion test/associations_test.rb
@@ -1,6 +1,6 @@
require 'test_helper'

module Spike
module Spyke
class AssociationsTest < MiniTest::Test
def test_association_independence
assert_kind_of Associations::HasMany, Recipe.new.groups
Expand Down
4 changes: 2 additions & 2 deletions test/attributes_test.rb
@@ -1,6 +1,6 @@
require 'test_helper'

module Spike
module Spyke
class AttributesTest < MiniTest::Test
def test_predicate_methods
stub_request(:get, 'http://sushi.com/recipes/1').to_return_json(data: { id: 1, title: 'Sushi' })
Expand Down Expand Up @@ -48,7 +48,7 @@ def test_setters
def test_equality
assert_equal Recipe.new(id: 2, title: 'Fish'), Recipe.new(id: 2, title: 'Fish')
refute_equal Recipe.new(id: 2, title: 'Fish'), Recipe.new(id: 1, title: 'Fish')
refute_equal Recipe.new(id: 2, title: 'Fish'), 'not_a_spike_object'
refute_equal Recipe.new(id: 2, title: 'Fish'), 'not_a_spyke_object'
end

def test_explicit_attributes
Expand Down
2 changes: 1 addition & 1 deletion test/callbacks_test.rb
@@ -1,6 +1,6 @@
require 'test_helper'

module Spike
module Spyke
class CallbacksTest < MiniTest::Test
def setup
stub_request(:any, /.*/)
Expand Down
2 changes: 1 addition & 1 deletion test/custom_request_test.rb
@@ -1,6 +1,6 @@
require 'test_helper'

module Spike
module Spyke
class CustomRequestTest < MiniTest::Test
def test_custom_get_request_from_class
endpoint = stub_request(:get, 'http://sushi.com/recipes/recent').to_return_json(data: [{ id: 1, title: 'Bread' }])
Expand Down
2 changes: 1 addition & 1 deletion test/orm_test.rb
@@ -1,6 +1,6 @@
require 'test_helper'

module Spike
module Spyke
class OrmTest < MiniTest::Test
def test_find
stub_request(:get, 'http://sushi.com/recipes/1').to_return_json(data: { id: 1, title: 'Sushi' })
Expand Down

0 comments on commit 4f42f8c

Please sign in to comment.