her 0.0.1
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 +6 -0
- data/Gemfile +2 -0
- data/README.md +36 -0
- data/Rakefile +28 -0
- data/her.gemspec +29 -0
- data/lib/her/api.rb +59 -0
- data/lib/her/model/base.rb +7 -0
- data/lib/her/model/http.rb +39 -0
- data/lib/her/model/orm.rb +40 -0
- data/lib/her/model/relationships.rb +56 -0
- data/lib/her/model.rb +32 -0
- data/lib/her/version.rb +3 -0
- data/lib/her.rb +10 -0
- data/spec/api_spec.rb +52 -0
- data/spec/model_spec.rb +66 -0
- data/spec/spec_helper.rb +12 -0
- metadata +216 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# Her
|
2
|
+
|
3
|
+
[](http://travis-ci.org/remiprev/her)
|
4
|
+
|
5
|
+
Her is an ORM (Object Relational Mapper) that maps REST resources to Ruby objects. It is designed to build applications that are powered by a RESTful API.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
In your Gemfile, add:
|
10
|
+
|
11
|
+
gem "her"
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
To add the ORM to a class, you just have to include `Her::Model` in it and define which API you want it to be bound to. For example, with Rails, you would define a `config/initializers/her.rb` file with this:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
$my_api = Her::API.new
|
19
|
+
$my_api.setup :base_uri => "https://api.example.com"
|
20
|
+
```
|
21
|
+
|
22
|
+
And then, for each of your models:
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
class User
|
26
|
+
include Her::Model
|
27
|
+
uses_api $my_api
|
28
|
+
end
|
29
|
+
```
|
30
|
+
|
31
|
+
After that, using Her is very similar to many ActiveModel-like ORMs:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
User.all # => Fetches "https://api.example.com/users" and return an array of User objects
|
35
|
+
User.find(1) # => Fetches "https://api.example.com/users/1" and return a User object
|
36
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require "bundler"
|
2
|
+
Bundler.require :development
|
3
|
+
|
4
|
+
require "bundler/gem_tasks"
|
5
|
+
require "rspec/core/rake_task"
|
6
|
+
|
7
|
+
task :default => :spec
|
8
|
+
|
9
|
+
desc "Run all specs"
|
10
|
+
RSpec::Core::RakeTask.new(:spec) do |task| # {{{
|
11
|
+
task.pattern = "spec/**/*_spec.rb"
|
12
|
+
task.rspec_opts = "--colour --format=documentation"
|
13
|
+
end # }}}
|
14
|
+
|
15
|
+
desc "Generate YARD Documentation"
|
16
|
+
YARD::Rake::YardocTask.new do |task| # {{{
|
17
|
+
task.options = [
|
18
|
+
"-o", File.expand_path("../doc", __FILE__),
|
19
|
+
"--readme=README.md",
|
20
|
+
"--markup=markdown",
|
21
|
+
"--markup-provider=maruku",
|
22
|
+
"--no-private",
|
23
|
+
"--no-cache",
|
24
|
+
"--protected",
|
25
|
+
"--title=Her",
|
26
|
+
]
|
27
|
+
task.files = ["lib/**/*.rb"]
|
28
|
+
end # }}}
|
data/her.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "her/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "her"
|
7
|
+
s.version = Her::VERSION
|
8
|
+
s.authors = ["Rémi Prévost"]
|
9
|
+
s.email = ["remi@exomel.com"]
|
10
|
+
s.homepage = "https://github.com/remiprev/her"
|
11
|
+
s.summary = "A simple Representational State Transfer-based Hypertext Transfer Protocol-powered Object Relational Mapper. Her?"
|
12
|
+
s.description = "Her is an ORM that maps REST resources to Ruby objects"
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
|
19
|
+
s.add_development_dependency "rake"
|
20
|
+
s.add_development_dependency "rspec"
|
21
|
+
s.add_development_dependency "yard"
|
22
|
+
s.add_development_dependency "maruku"
|
23
|
+
s.add_development_dependency "mocha"
|
24
|
+
s.add_development_dependency "fakeweb"
|
25
|
+
|
26
|
+
s.add_runtime_dependency "activesupport"
|
27
|
+
s.add_runtime_dependency "faraday"
|
28
|
+
s.add_runtime_dependency "json"
|
29
|
+
end
|
data/lib/her/api.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
module Her
|
2
|
+
# This class is where all HTTP requests are made. Before using Her, you must configure it
|
3
|
+
# so it knows where to make those requests. In Rails, this is usually done in `config/initializers/her.rb`:
|
4
|
+
#
|
5
|
+
# @example
|
6
|
+
# $my_api = Her::API.new
|
7
|
+
# $my_api.setup :base_uri => "https://api.example.com"
|
8
|
+
class API
|
9
|
+
# @private
|
10
|
+
attr_reader :base_uri, :parse_with
|
11
|
+
|
12
|
+
# Setup the API connection
|
13
|
+
def setup(attrs={}) # {{{
|
14
|
+
@base_uri = attrs[:base_uri]
|
15
|
+
@parse_with = lambda do |response|
|
16
|
+
json = JSON.parse(response.body, :symbolize_names => true)
|
17
|
+
{
|
18
|
+
:resource => json[:data],
|
19
|
+
:errors => json[:errors],
|
20
|
+
:metadata => json[:metadata],
|
21
|
+
}
|
22
|
+
end
|
23
|
+
@connection = Faraday.new(:url => @base_uri) do |builder|
|
24
|
+
builder.request :url_encoded
|
25
|
+
builder.adapter :net_http
|
26
|
+
end
|
27
|
+
end # }}}
|
28
|
+
|
29
|
+
# Define a custom parsing procedure. The procedure is passed the response object and is
|
30
|
+
# expected to return hash with three keys: a main resource Hash, an errors Array
|
31
|
+
# and a metadata Hash.
|
32
|
+
#
|
33
|
+
# @example
|
34
|
+
# $my_api.parse_with do |response|
|
35
|
+
# json = JSON.parse(response.body)
|
36
|
+
# { :resource => json[:data], :errors => json[:errors], :metadata => json[:metdata] }
|
37
|
+
# end
|
38
|
+
def parse_with(&block) # {{{
|
39
|
+
@custom_parsing_block = true
|
40
|
+
@parse_with = block
|
41
|
+
end # }}}
|
42
|
+
|
43
|
+
# Return whether a custom parsing block has been defined
|
44
|
+
def custom_parsing_block? # {{{
|
45
|
+
@custom_parsing_block
|
46
|
+
end # }}}
|
47
|
+
|
48
|
+
# Make an HTTP request to the API
|
49
|
+
def request(attrs={}) # {{{
|
50
|
+
# TODO Here, we would probably look for hooks that modify the request before calling the API
|
51
|
+
@connection.send(attrs[:method], attrs[:path])
|
52
|
+
end # }}}
|
53
|
+
|
54
|
+
# Parse the HTTP response
|
55
|
+
def parse(response) # {{{
|
56
|
+
@parse_with.call(response)
|
57
|
+
end # }}}
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Her
|
2
|
+
module Model
|
3
|
+
# This module interacts with Her::API to fetch HTTP data
|
4
|
+
module HTTP
|
5
|
+
# Link a model with a Her::API object
|
6
|
+
def uses_api(api) # {{{
|
7
|
+
@her_api = api
|
8
|
+
end # }}}
|
9
|
+
|
10
|
+
# Defines a custom collection path for the resource
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
# class User
|
14
|
+
# include Her::Model
|
15
|
+
# uses_api $example_api
|
16
|
+
# collection_path "users"
|
17
|
+
# end
|
18
|
+
def collection_path(path=nil) # {{{
|
19
|
+
return @her_collection_path unless path
|
20
|
+
@her_collection_path = path
|
21
|
+
end # }}}
|
22
|
+
|
23
|
+
# Main request wrapper around Her::API. Used to make custom request to the API.
|
24
|
+
# @private
|
25
|
+
def request(attrs={}, &block) # {{{
|
26
|
+
response = @her_api.request(attrs)
|
27
|
+
yield @her_api.parse(response)
|
28
|
+
end # }}}
|
29
|
+
|
30
|
+
# Make a GET request and return the parsed JSON response
|
31
|
+
#
|
32
|
+
# @example
|
33
|
+
# User.get "/users/foo"
|
34
|
+
def get(path, attrs={}, &block) # {{{
|
35
|
+
request(attrs.merge(:method => :get, :path => path), &block)
|
36
|
+
end # }}}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Her
|
2
|
+
module Model
|
3
|
+
# This module adds ORM-like capabilities to the model
|
4
|
+
module ORM
|
5
|
+
# Initialize a new object with data received from an HTTP request
|
6
|
+
# @private
|
7
|
+
def initialize(single_data) # {{{
|
8
|
+
@data = single_data
|
9
|
+
@data = self.class.parse_relationships(@data)
|
10
|
+
end # }}}
|
11
|
+
|
12
|
+
# Initialize a collection of resources
|
13
|
+
# @private
|
14
|
+
def self.initialize_collection(name, collection_data) # {{{
|
15
|
+
collection_data.map { |item_data| Object.const_get(name.to_s.classify).new(item_data) }
|
16
|
+
end # }}}
|
17
|
+
|
18
|
+
# Handles missing methods
|
19
|
+
# @private
|
20
|
+
def method_missing(method) # {{{
|
21
|
+
method = method.to_s.gsub(/(\?|\!)$/, "").to_sym
|
22
|
+
@data.include?(method) ? @data[method] : super
|
23
|
+
end # }}}
|
24
|
+
|
25
|
+
# Fetch a specific resource based on an ID
|
26
|
+
def find(id) # {{{
|
27
|
+
request(:method => :get, :path => "#{@her_collection_path}/#{id}") do |parsed_data|
|
28
|
+
new(parsed_data[:resource])
|
29
|
+
end
|
30
|
+
end # }}}
|
31
|
+
|
32
|
+
# Fetch a collection of resources
|
33
|
+
def all(params={}) # {{{
|
34
|
+
request(:method => :get, :path => "#{@her_collection_path}") do |parsed_data|
|
35
|
+
Her::Model::ORM.initialize_collection(to_s.downcase.pluralize, parsed_data[:resource])
|
36
|
+
end
|
37
|
+
end # }}}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Her
|
2
|
+
module Model
|
3
|
+
# This module adds relationships to models
|
4
|
+
module Relationships
|
5
|
+
# Return relationships
|
6
|
+
# @private
|
7
|
+
def relationships # {{{
|
8
|
+
@her_relationships
|
9
|
+
end # }}}
|
10
|
+
|
11
|
+
# Parse relationships data after initializing a new object
|
12
|
+
# @private
|
13
|
+
def parse_relationships(data) # {{{
|
14
|
+
@her_relationships ||= {}
|
15
|
+
@her_relationships.each_pair do |type, relationships|
|
16
|
+
relationships.each do |relationship|
|
17
|
+
data[relationship[:name]] = Her::Model::ORM.initialize_collection(relationship[:name], data[relationship[:name]]) if data.include?(relationship[:name])
|
18
|
+
end
|
19
|
+
end
|
20
|
+
data
|
21
|
+
end # }}}
|
22
|
+
|
23
|
+
# Define an *has_many* relationship for the resource
|
24
|
+
#
|
25
|
+
# * `User.has_many :comments` is used to check if the "user" JSON
|
26
|
+
# resource we receive has a `comments` key and map it to an array
|
27
|
+
# of Comment.new objects
|
28
|
+
# * `User.has_many :comments` creates a User.comments method to would
|
29
|
+
# make an extra HTTP request if there was no "comments" key
|
30
|
+
def has_many(name, attrs={}) # {{{
|
31
|
+
@her_relationships ||= {}
|
32
|
+
(@her_relationships[:has_many] ||= []) << attrs.merge(:name => name)
|
33
|
+
collection_path = @her_collection_path
|
34
|
+
|
35
|
+
define_method(name) do
|
36
|
+
return @data[name] if @data.include?(name) # Do not fetch from API again if we have it in @data
|
37
|
+
self.class.get("#{collection_path}/#{id}/#{Object.const_get(name.to_s.classify).collection_path}") do |parsed_data|
|
38
|
+
@data[name] = Her::Model::ORM.initialize_collection(name, parsed_data[:resource])
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end # }}}
|
42
|
+
|
43
|
+
# Define a *belongs_to* relationship for the resource
|
44
|
+
#
|
45
|
+
# * `User.belongs_to :organzation` is used to check if the "user" JSON
|
46
|
+
# resource we receive has an `organzation` key and map it to
|
47
|
+
# an Organization.new object
|
48
|
+
#
|
49
|
+
# * `User.belongs_to :organzation` creates a User.organzation method
|
50
|
+
def belongs_to(name, attrs={}) # {{{
|
51
|
+
@her_relationships ||= {}
|
52
|
+
(@her_relationships[:belongs_to] ||= []) << attrs.merge(:name => name)
|
53
|
+
end # }}}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/her/model.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
module Her
|
2
|
+
# This module is the main element of Her. After creating a Her::API object,
|
3
|
+
# include this module in your models to get a few magic methods defined in them.
|
4
|
+
#
|
5
|
+
# @example
|
6
|
+
# class User
|
7
|
+
# include Her::Model
|
8
|
+
# uses_api $api
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# @user = User.new(:name => "Rémi")
|
12
|
+
module Model
|
13
|
+
autoload :Base, "her/model/base"
|
14
|
+
autoload :HTTP, "her/model/http"
|
15
|
+
autoload :ORM, "her/model/orm"
|
16
|
+
autoload :Relationships, "her/model/relationships"
|
17
|
+
|
18
|
+
extend ActiveSupport::Concern
|
19
|
+
|
20
|
+
# Instance methods
|
21
|
+
include Her::Model::ORM
|
22
|
+
|
23
|
+
# Class methods
|
24
|
+
included do
|
25
|
+
@her_collection_path = "#{self.to_s.downcase.pluralize}"
|
26
|
+
extend Her::Model::Base
|
27
|
+
extend Her::Model::HTTP
|
28
|
+
extend Her::Model::ORM
|
29
|
+
extend Her::Model::Relationships
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/her/version.rb
ADDED
data/lib/her.rb
ADDED
data/spec/api_spec.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.join(File.dirname(__FILE__), "spec_helper.rb")
|
3
|
+
|
4
|
+
describe Her::API do
|
5
|
+
context "initialization" do
|
6
|
+
describe "#setup" do
|
7
|
+
it "sets a base URI" do # {{{
|
8
|
+
@api = Her::API.new
|
9
|
+
@api.setup :base_uri => "https://api.example.com"
|
10
|
+
@api.base_uri.should == "https://api.example.com"
|
11
|
+
end # }}}
|
12
|
+
|
13
|
+
it "sets a custom parsing block" do # {{{
|
14
|
+
@api = Her::API.new
|
15
|
+
@api.setup :base_uri => "https://api.example.com"
|
16
|
+
@api.parse_with do |response|
|
17
|
+
response.body
|
18
|
+
end
|
19
|
+
@api.custom_parsing_block?.should be_true
|
20
|
+
end # }}}
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#request" do
|
24
|
+
before do # {{{
|
25
|
+
@api = Her::API.new
|
26
|
+
@api.setup :base_uri => "https://api.example.com"
|
27
|
+
FakeWeb.register_uri(:get, "https://api.example.com/foo", :body => "Foo, it is.")
|
28
|
+
end # }}}
|
29
|
+
|
30
|
+
it "makes HTTP requests" do # {{{
|
31
|
+
response = @api.request(:method => :get, :path => "/foo")
|
32
|
+
response.body.should == "Foo, it is."
|
33
|
+
end # }}}
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "#parse" do
|
37
|
+
before do # {{{
|
38
|
+
@api = Her::API.new
|
39
|
+
@api.setup :base_uri => "https://api.example.com"
|
40
|
+
FakeWeb.register_uri(:get, "https://api.example.com/users/1", :body => { :data => { :id => 1, :name => "George Michael Bluth" }, :errors => ["This is a single error"], :metadata => { :page => 1, :per_page => 10 }}.to_json)
|
41
|
+
end # }}}
|
42
|
+
|
43
|
+
it "parses a request" do # {{{
|
44
|
+
@api.parse @api.request(:method => :get, :path => "users/1") do |parsed_data|
|
45
|
+
parsed_data[:resource].should == { :id => 1, :name => "George Michael Bluth" }
|
46
|
+
parsed_data[:errors].should == ["This is a single error"]
|
47
|
+
parsed_data[:metadata].should == { :page => 1, :per_page => 10 }
|
48
|
+
end
|
49
|
+
end # }}}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/spec/model_spec.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.join(File.dirname(__FILE__), "spec_helper.rb")
|
3
|
+
|
4
|
+
describe Her::Model do
|
5
|
+
describe Her::Model::ORM do
|
6
|
+
context "mapping data to Ruby objects" do # {{{
|
7
|
+
before do # {{{
|
8
|
+
@api = Her::API.new
|
9
|
+
@api.setup :base_uri => "https://api.example.com"
|
10
|
+
FakeWeb.register_uri(:get, "https://api.example.com/users/1", :body => { :data => { :id => 1, :name => "Tobias Fünke" } }.to_json)
|
11
|
+
FakeWeb.register_uri(:get, "https://api.example.com/users", :body => { :data => [{ :id => 1, :name => "Tobias Fünke" }, { :id => 2, :name => "Lindsay Fünke" }] }.to_json)
|
12
|
+
|
13
|
+
Object.instance_eval { remove_const :User } if Object.const_defined?(:User)
|
14
|
+
class User
|
15
|
+
include Her::Model
|
16
|
+
end
|
17
|
+
User.uses_api @api
|
18
|
+
end # }}}
|
19
|
+
|
20
|
+
it "maps a single resource to a Ruby object" do # {{{
|
21
|
+
@user = User.find(1)
|
22
|
+
@user.id.should == 1
|
23
|
+
@user.name.should == "Tobias Fünke"
|
24
|
+
end # }}}
|
25
|
+
|
26
|
+
it "maps a collection of resources to an array of Ruby objects" do # {{{
|
27
|
+
@users = User.all
|
28
|
+
@users.length.should == 2
|
29
|
+
@users.first.name.should == "Tobias Fünke"
|
30
|
+
end # }}}
|
31
|
+
end # }}}
|
32
|
+
end
|
33
|
+
|
34
|
+
describe Her::Model::Relationships do
|
35
|
+
context "setting associations" do # {{{
|
36
|
+
before do # {{{
|
37
|
+
Object.instance_eval { remove_const :User } if Object.const_defined?(:User)
|
38
|
+
class User
|
39
|
+
include Her::Model
|
40
|
+
end
|
41
|
+
end # }}}
|
42
|
+
|
43
|
+
it "handles a single 'has_many' association" do # {{{
|
44
|
+
User.has_many :comments
|
45
|
+
User.relationships[:has_many].should == [{ :name => :comments }]
|
46
|
+
end # }}}
|
47
|
+
|
48
|
+
it "handles multiples 'has_many' associations" do # {{{
|
49
|
+
User.has_many :comments
|
50
|
+
User.has_many :posts
|
51
|
+
User.relationships[:has_many].should == [{ :name => :comments }, { :name => :posts }]
|
52
|
+
end # }}}
|
53
|
+
|
54
|
+
it "handles a single belongs_to association" do # {{{
|
55
|
+
User.belongs_to :organization
|
56
|
+
User.relationships[:belongs_to].should == [{ :name => :organization }]
|
57
|
+
end # }}}
|
58
|
+
|
59
|
+
it "handles multiples 'belongs_to' associations" do # {{{
|
60
|
+
User.belongs_to :organization
|
61
|
+
User.belongs_to :family
|
62
|
+
User.relationships[:belongs_to].should == [{ :name => :organization }, { :name => :family }]
|
63
|
+
end # }}}
|
64
|
+
end # }}}
|
65
|
+
end
|
66
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,216 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: her
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Rémi Prévost
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-04-09 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rspec
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: yard
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: maruku
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: mocha
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: fakeweb
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: activesupport
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: faraday
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
type: :runtime
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ! '>='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
- !ruby/object:Gem::Dependency
|
143
|
+
name: json
|
144
|
+
requirement: !ruby/object:Gem::Requirement
|
145
|
+
none: false
|
146
|
+
requirements:
|
147
|
+
- - ! '>='
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0'
|
150
|
+
type: :runtime
|
151
|
+
prerelease: false
|
152
|
+
version_requirements: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ! '>='
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0'
|
158
|
+
description: Her is an ORM that maps REST resources to Ruby objects
|
159
|
+
email:
|
160
|
+
- remi@exomel.com
|
161
|
+
executables: []
|
162
|
+
extensions: []
|
163
|
+
extra_rdoc_files: []
|
164
|
+
files:
|
165
|
+
- .gitignore
|
166
|
+
- Gemfile
|
167
|
+
- README.md
|
168
|
+
- Rakefile
|
169
|
+
- her.gemspec
|
170
|
+
- lib/her.rb
|
171
|
+
- lib/her/api.rb
|
172
|
+
- lib/her/model.rb
|
173
|
+
- lib/her/model/base.rb
|
174
|
+
- lib/her/model/http.rb
|
175
|
+
- lib/her/model/orm.rb
|
176
|
+
- lib/her/model/relationships.rb
|
177
|
+
- lib/her/version.rb
|
178
|
+
- spec/api_spec.rb
|
179
|
+
- spec/model_spec.rb
|
180
|
+
- spec/spec_helper.rb
|
181
|
+
homepage: https://github.com/remiprev/her
|
182
|
+
licenses: []
|
183
|
+
post_install_message:
|
184
|
+
rdoc_options: []
|
185
|
+
require_paths:
|
186
|
+
- lib
|
187
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
188
|
+
none: false
|
189
|
+
requirements:
|
190
|
+
- - ! '>='
|
191
|
+
- !ruby/object:Gem::Version
|
192
|
+
version: '0'
|
193
|
+
segments:
|
194
|
+
- 0
|
195
|
+
hash: 1076475942848490039
|
196
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
197
|
+
none: false
|
198
|
+
requirements:
|
199
|
+
- - ! '>='
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: '0'
|
202
|
+
segments:
|
203
|
+
- 0
|
204
|
+
hash: 1076475942848490039
|
205
|
+
requirements: []
|
206
|
+
rubyforge_project:
|
207
|
+
rubygems_version: 1.8.18
|
208
|
+
signing_key:
|
209
|
+
specification_version: 3
|
210
|
+
summary: A simple Representational State Transfer-based Hypertext Transfer Protocol-powered
|
211
|
+
Object Relational Mapper. Her?
|
212
|
+
test_files:
|
213
|
+
- spec/api_spec.rb
|
214
|
+
- spec/model_spec.rb
|
215
|
+
- spec/spec_helper.rb
|
216
|
+
has_rdoc:
|