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 ADDED
@@ -0,0 +1,6 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .yardoc
6
+ doc
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source :rubygems
2
+ gemspec
data/README.md ADDED
@@ -0,0 +1,36 @@
1
+ # Her
2
+
3
+ [![Build Status](https://secure.travis-ci.org/remiprev/her.png)](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,7 @@
1
+ module Her
2
+ module Model
3
+ # This module includes basic functionnality to Her::Model
4
+ module Base
5
+ end
6
+ end
7
+ 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
@@ -0,0 +1,3 @@
1
+ module Her
2
+ VERSION = "0.0.1"
3
+ end
data/lib/her.rb ADDED
@@ -0,0 +1,10 @@
1
+ require "her/version"
2
+ require "json"
3
+ require "faraday"
4
+ require "active_support"
5
+ require "active_support/inflector"
6
+
7
+ module Her
8
+ autoload :Model, "her/model"
9
+ autoload :API, "her/api"
10
+ end
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
@@ -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
@@ -0,0 +1,12 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
2
+
3
+ require "her"
4
+ require "fakeweb"
5
+ require "mocha"
6
+
7
+ module Helpers
8
+ end
9
+
10
+ RSpec.configure do |c|
11
+ c.include Helpers
12
+ end
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: