her 0.5.3 → 0.5.4
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.
- checksums.yaml +8 -8
- data/.gitignore +2 -2
- data/.rspec +1 -2
- data/.travis.yml +2 -2
- data/README.md +10 -16
- data/UPGRADE.md +4 -0
- data/examples/grape-and-her/.env.default +3 -0
- data/examples/grape-and-her/Procfile +2 -0
- data/examples/grape-and-her/README.md +27 -0
- data/examples/grape-and-her/api/Gemfile +11 -0
- data/examples/grape-and-her/api/Rakefile +14 -0
- data/examples/grape-and-her/api/app/api.rb +49 -0
- data/examples/grape-and-her/api/app/models/organization.rb +7 -0
- data/examples/grape-and-her/api/app/models/user.rb +9 -0
- data/examples/grape-and-her/api/app/views/organizations/_base.rabl +2 -0
- data/examples/grape-and-her/api/app/views/organizations/index.rabl +3 -0
- data/examples/grape-and-her/api/app/views/organizations/show.rabl +3 -0
- data/examples/grape-and-her/api/app/views/users/_base.rabl +8 -0
- data/examples/grape-and-her/api/app/views/users/index.rabl +3 -0
- data/examples/grape-and-her/api/app/views/users/show.rabl +3 -0
- data/examples/grape-and-her/api/config.ru +5 -0
- data/examples/grape-and-her/api/config/boot.rb +17 -0
- data/examples/grape-and-her/api/config/unicorn.rb +7 -0
- data/examples/grape-and-her/api/db/migrations/001_create_users.rb +11 -0
- data/examples/grape-and-her/api/db/migrations/002_create_organizations.rb +8 -0
- data/examples/grape-and-her/consumer/Gemfile +23 -0
- data/examples/grape-and-her/consumer/app/assets/stylesheets/application.scss +190 -0
- data/examples/grape-and-her/consumer/app/assets/stylesheets/reset.scss +53 -0
- data/examples/grape-and-her/consumer/app/consumer.rb +74 -0
- data/examples/grape-and-her/consumer/app/models/organization.rb +13 -0
- data/examples/grape-and-her/consumer/app/models/user.rb +13 -0
- data/examples/grape-and-her/consumer/app/views/index.haml +9 -0
- data/examples/grape-and-her/consumer/app/views/layout.haml +20 -0
- data/examples/grape-and-her/consumer/app/views/organizations/index.haml +25 -0
- data/examples/grape-and-her/consumer/app/views/organizations/show.haml +11 -0
- data/examples/grape-and-her/consumer/app/views/users/index.haml +33 -0
- data/examples/grape-and-her/consumer/app/views/users/show.haml +9 -0
- data/examples/grape-and-her/consumer/config.ru +20 -0
- data/examples/grape-and-her/consumer/config/boot.rb +30 -0
- data/examples/grape-and-her/consumer/config/unicorn.rb +7 -0
- data/examples/grape-and-her/consumer/lib/response_logger.rb +18 -0
- data/her.gemspec +2 -2
- data/lib/her/model.rb +22 -26
- data/lib/her/model/associations.rb +19 -19
- data/lib/her/model/attributes.rb +173 -0
- data/lib/her/model/base.rb +17 -0
- data/lib/her/model/http.rb +58 -242
- data/lib/her/model/introspection.rb +7 -8
- data/lib/her/model/nested_attributes.rb +3 -3
- data/lib/her/model/orm.rb +15 -205
- data/lib/her/model/parse.rb +86 -0
- data/lib/her/model/paths.rb +54 -14
- data/lib/her/version.rb +1 -1
- data/spec/model/attributes_spec.rb +139 -0
- data/spec/model/dirty_spec.rb +40 -0
- data/spec/model/introspection_spec.rb +5 -5
- data/spec/model/orm_spec.rb +14 -128
- data/spec/model/paths_spec.rb +26 -0
- data/spec/model/validations_spec.rb +17 -0
- data/spec/spec_helper.rb +7 -32
- data/spec/support/extensions/array.rb +5 -0
- data/spec/support/extensions/hash.rb +5 -0
- data/spec/support/macros/model_macros.rb +29 -0
- metadata +52 -15
- data/examples/twitter-oauth/Gemfile +0 -13
- data/examples/twitter-oauth/app.rb +0 -50
- data/examples/twitter-oauth/config.ru +0 -5
- data/examples/twitter-oauth/views/index.haml +0 -9
- data/examples/twitter-search/Gemfile +0 -12
- data/examples/twitter-search/app.rb +0 -55
- data/examples/twitter-search/config.ru +0 -5
- data/examples/twitter-search/views/index.haml +0 -9
@@ -18,12 +18,12 @@ module Her
|
|
18
18
|
alias :get_relationship :get_association
|
19
19
|
|
20
20
|
module ClassMethods
|
21
|
-
# Return @
|
21
|
+
# Return @_her_associations, lazily initialized with copy of the
|
22
22
|
# superclass' her_associations, or an empty hash.
|
23
23
|
#
|
24
24
|
# @private
|
25
25
|
def associations
|
26
|
-
@
|
26
|
+
@_her_associations ||= begin
|
27
27
|
if superclass.respond_to?(:associations)
|
28
28
|
superclass.associations.dup
|
29
29
|
else
|
@@ -42,12 +42,12 @@ module Her
|
|
42
42
|
data_key = association[:data_key]
|
43
43
|
next unless data[data_key]
|
44
44
|
|
45
|
-
klass = self.
|
45
|
+
klass = self.her_nearby_class(association[:class_name])
|
46
46
|
name = association[:name]
|
47
47
|
|
48
48
|
data[name] = case type
|
49
49
|
when :has_many
|
50
|
-
Her::Model::
|
50
|
+
Her::Model::Attributes.initialize_collection(klass, :data => data[data_key])
|
51
51
|
when :has_one, :belongs_to
|
52
52
|
klass.new(data[data_key])
|
53
53
|
else
|
@@ -65,12 +65,12 @@ module Her
|
|
65
65
|
#
|
66
66
|
# @example
|
67
67
|
# class User
|
68
|
-
# include Her::
|
68
|
+
# include Her::Model
|
69
69
|
# has_many :articles
|
70
70
|
# end
|
71
71
|
#
|
72
72
|
# class Article
|
73
|
-
# include Her::
|
73
|
+
# include Her::Model
|
74
74
|
# end
|
75
75
|
#
|
76
76
|
# @user = User.find(1)
|
@@ -88,13 +88,13 @@ module Her
|
|
88
88
|
|
89
89
|
define_method(name) do |*method_attrs|
|
90
90
|
method_attrs = method_attrs[0] || {}
|
91
|
-
klass = self.class.
|
91
|
+
klass = self.class.her_nearby_class(attrs[:class_name])
|
92
92
|
|
93
93
|
return Her::Collection.new if @attributes.include?(name) && @attributes[name].empty? && method_attrs.empty?
|
94
94
|
|
95
95
|
if @attributes[name].blank? || method_attrs.any?
|
96
96
|
path = begin
|
97
|
-
|
97
|
+
request_path(method_attrs)
|
98
98
|
rescue Her::Errors::PathError
|
99
99
|
return nil
|
100
100
|
end
|
@@ -115,16 +115,16 @@ module Her
|
|
115
115
|
# Define an *has_one* association.
|
116
116
|
#
|
117
117
|
# @param [Symbol] name The name of the model
|
118
|
-
# @param [Hash] attrs Options
|
118
|
+
# @param [Hash] attrs Options
|
119
119
|
#
|
120
120
|
# @example
|
121
121
|
# class User
|
122
|
-
# include Her::
|
122
|
+
# include Her::Model
|
123
123
|
# has_one :organization
|
124
124
|
# end
|
125
125
|
#
|
126
126
|
# class Organization
|
127
|
-
# include Her::
|
127
|
+
# include Her::Model
|
128
128
|
# end
|
129
129
|
#
|
130
130
|
# @user = User.find(1)
|
@@ -141,13 +141,13 @@ module Her
|
|
141
141
|
|
142
142
|
define_method(name) do |*method_attrs|
|
143
143
|
method_attrs = method_attrs[0] || {}
|
144
|
-
klass = self.class.
|
144
|
+
klass = self.class.her_nearby_class(attrs[:class_name])
|
145
145
|
|
146
146
|
return nil if @attributes.include?(name) && @attributes[name].nil? && method_attrs.empty?
|
147
147
|
|
148
148
|
if @attributes[name].blank? || method_attrs.any?
|
149
149
|
path = begin
|
150
|
-
|
150
|
+
request_path(method_attrs)
|
151
151
|
rescue Her::Errors::PathError
|
152
152
|
return nil
|
153
153
|
end
|
@@ -162,19 +162,19 @@ module Her
|
|
162
162
|
# Define a *belongs_to* association.
|
163
163
|
#
|
164
164
|
# @param [Symbol] name The name of the model
|
165
|
-
# @param [Hash] attrs Options
|
165
|
+
# @param [Hash] attrs Options
|
166
166
|
#
|
167
167
|
# @example
|
168
168
|
# class User
|
169
|
-
# include Her::
|
169
|
+
# include Her::Model
|
170
170
|
# belongs_to :team, :class_name => "Group"
|
171
171
|
# end
|
172
172
|
#
|
173
173
|
# class Group
|
174
|
-
# include Her::
|
174
|
+
# include Her::Model
|
175
175
|
# end
|
176
176
|
#
|
177
|
-
# @user = User.find(1)
|
177
|
+
# @user = User.find(1) # => #<User(users/1) id=1 team_id=2 name="Tobias">
|
178
178
|
# @user.team # => #<Team(teams/2) id=2 name="Developers">
|
179
179
|
# # Fetched via GET "/teams/2"
|
180
180
|
def belongs_to(name, attrs={})
|
@@ -189,13 +189,13 @@ module Her
|
|
189
189
|
|
190
190
|
define_method(name) do |*method_attrs|
|
191
191
|
method_attrs = method_attrs[0] || {}
|
192
|
-
klass = self.class.
|
192
|
+
klass = self.class.her_nearby_class(attrs[:class_name])
|
193
193
|
|
194
194
|
return nil if @attributes.include?(name) && @attributes[name].nil? && method_attrs.empty?
|
195
195
|
|
196
196
|
if @attributes[name].blank? || method_attrs.any?
|
197
197
|
path = begin
|
198
|
-
klass.build_request_path(@attributes.merge(method_attrs.merge(
|
198
|
+
klass.build_request_path(@attributes.merge(method_attrs.merge(klass.primary_key => @attributes[attrs[:foreign_key].to_sym])))
|
199
199
|
rescue Her::Errors::PathError
|
200
200
|
return nil
|
201
201
|
end
|
@@ -0,0 +1,173 @@
|
|
1
|
+
module Her
|
2
|
+
module Model
|
3
|
+
# This module handles all methods related to model attributes
|
4
|
+
module Attributes
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
attr_accessor :attributes, :metadata, :response_errors
|
8
|
+
alias :data :attributes
|
9
|
+
alias :data= :attributes=
|
10
|
+
|
11
|
+
# Initialize a new object with data
|
12
|
+
def initialize(attributes={})
|
13
|
+
attributes ||= {}
|
14
|
+
@metadata = attributes.delete(:_metadata) || {}
|
15
|
+
@response_errors = attributes.delete(:_errors) || {}
|
16
|
+
@destroyed = attributes.delete(:_destroyed) || false
|
17
|
+
|
18
|
+
assign_attributes(attributes)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Initialize a collection of resources
|
22
|
+
# @private
|
23
|
+
def self.initialize_collection(klass, parsed_data={})
|
24
|
+
collection_data = parsed_data[:data].map do |item_data|
|
25
|
+
resource = klass.new(klass.parse(item_data))
|
26
|
+
resource.run_callbacks :find
|
27
|
+
resource
|
28
|
+
end
|
29
|
+
Her::Collection.new(collection_data, parsed_data[:metadata], parsed_data[:errors])
|
30
|
+
end
|
31
|
+
|
32
|
+
# Use setter methods of model for each key / value pair in params
|
33
|
+
# Return key / value pairs for which no setter method was defined on the model
|
34
|
+
# @private
|
35
|
+
def self.use_setter_methods(model, params)
|
36
|
+
setter_method_names = model.class.setter_method_names
|
37
|
+
params ||= {}
|
38
|
+
params.inject({}) do |memo, (key, value)|
|
39
|
+
setter_method = key.to_s + '='
|
40
|
+
if setter_method_names.include?(setter_method)
|
41
|
+
model.send(setter_method, value)
|
42
|
+
else
|
43
|
+
if key.is_a?(String)
|
44
|
+
key = key.to_sym
|
45
|
+
end
|
46
|
+
memo[key] = value
|
47
|
+
end
|
48
|
+
memo
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Handles missing methods
|
53
|
+
# @private
|
54
|
+
def method_missing(method, *args, &blk)
|
55
|
+
if method.to_s =~ /[?=]$/ || attributes.include?(method)
|
56
|
+
# Extract the attribute
|
57
|
+
attribute = method.to_s.sub(/[?=]$/, '')
|
58
|
+
|
59
|
+
# Create a new `attribute` methods set
|
60
|
+
self.class.attributes(*attribute)
|
61
|
+
|
62
|
+
# Resend the method!
|
63
|
+
send(method, *args, &blk)
|
64
|
+
else
|
65
|
+
super
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# @private
|
70
|
+
def respond_to?(method, include_private = false)
|
71
|
+
method.to_s.end_with?('=') || method.to_s.end_with?('?') || @attributes.include?(method) || super
|
72
|
+
end
|
73
|
+
|
74
|
+
# @private
|
75
|
+
def respond_to_missing?(method, include_private = false)
|
76
|
+
method.to_s.end_with?('=') || method.to_s.end_with?('?') || @attributes.include?(method) || @attributes.include?(method) || super
|
77
|
+
end
|
78
|
+
|
79
|
+
# Assign new attributes
|
80
|
+
# @private
|
81
|
+
def assign_attributes(raw_data)
|
82
|
+
@attributes ||= {}
|
83
|
+
# Use setter methods first, then translate attributes of associations
|
84
|
+
# into association instances, then merge the parsed_data into @attributes.
|
85
|
+
unset_attributes = Her::Model::Attributes.use_setter_methods(self, raw_data)
|
86
|
+
parsed_attributes = self.class.parse_associations(unset_attributes)
|
87
|
+
attributes.update(parsed_attributes)
|
88
|
+
end
|
89
|
+
alias :update_attributes :assign_attributes
|
90
|
+
alias :assign_data :assign_attributes
|
91
|
+
|
92
|
+
# Handles returning true for the accessible attributes
|
93
|
+
# @private
|
94
|
+
def has_attribute?(attribute_name)
|
95
|
+
attributes.include?(attribute_name)
|
96
|
+
end
|
97
|
+
alias :has_data? :has_attribute?
|
98
|
+
|
99
|
+
# Handles returning data for a specific attribute
|
100
|
+
# @private
|
101
|
+
def get_attribute(attribute_name)
|
102
|
+
attributes[attribute_name]
|
103
|
+
end
|
104
|
+
alias :get_data :get_attribute
|
105
|
+
|
106
|
+
# Override the method to prevent from returning the object ID
|
107
|
+
# @private
|
108
|
+
def id
|
109
|
+
attributes[self.class.primary_key] || super
|
110
|
+
end
|
111
|
+
|
112
|
+
# Return `true` if the other object is also a Her::Model and has matching data
|
113
|
+
# @private
|
114
|
+
def ==(other)
|
115
|
+
other.is_a?(Her::Model) && attributes == other.attributes
|
116
|
+
end
|
117
|
+
|
118
|
+
# Delegate to the == method
|
119
|
+
# @private
|
120
|
+
def eql?(other)
|
121
|
+
self == other
|
122
|
+
end
|
123
|
+
|
124
|
+
# Delegate to @attributes, allowing models to act correctly in code like:
|
125
|
+
# [ Model.find(1), Model.find(1) ].uniq # => [ Model.find(1) ]
|
126
|
+
# @private
|
127
|
+
def hash
|
128
|
+
attributes.hash
|
129
|
+
end
|
130
|
+
|
131
|
+
module ClassMethods
|
132
|
+
# Initialize a collection of resources with raw data from an HTTP request
|
133
|
+
#
|
134
|
+
# @param [Array] parsed_data
|
135
|
+
def new_collection(parsed_data)
|
136
|
+
Her::Model::Attributes.initialize_collection(self, parsed_data)
|
137
|
+
end
|
138
|
+
|
139
|
+
# Define the attributes that will be used to track dirty attributes and validations
|
140
|
+
#
|
141
|
+
# @param [Array] attributes
|
142
|
+
def attributes(*attributes)
|
143
|
+
define_attribute_methods attributes
|
144
|
+
|
145
|
+
attributes.each do |attribute|
|
146
|
+
attribute = attribute.to_sym
|
147
|
+
|
148
|
+
define_method "#{attribute}".to_sym do
|
149
|
+
@attributes.include?(attribute) ? @attributes[attribute] : nil
|
150
|
+
end
|
151
|
+
|
152
|
+
define_method "#{attribute}=".to_sym do |value|
|
153
|
+
self.send("#{attribute}_will_change!".to_sym) if @attributes[attribute] != value
|
154
|
+
@attributes[attribute] = value
|
155
|
+
end
|
156
|
+
|
157
|
+
define_method "#{attribute}?".to_sym do
|
158
|
+
@attributes.include?(attribute) && @attributes[attribute].present?
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
# @private
|
164
|
+
def setter_method_names
|
165
|
+
@_her_setter_method_names ||= instance_methods.inject(Set.new) do |memo, method_name|
|
166
|
+
memo << method_name.to_s if method_name.to_s.end_with?('=')
|
167
|
+
memo
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
data/lib/her/model/base.rb
CHANGED
@@ -2,6 +2,23 @@ module Her
|
|
2
2
|
module Model
|
3
3
|
# This module includes basic functionnality to Her::Model
|
4
4
|
module Base
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
# Returns true if attribute_name is
|
8
|
+
# * in resource attributes
|
9
|
+
# * an association
|
10
|
+
def has_key?(attribute_name)
|
11
|
+
has_attribute?(attribute_name) ||
|
12
|
+
has_association?(attribute_name)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns
|
16
|
+
# * the value of the attribute_name attribute if it's in orm data
|
17
|
+
# * the resource/collection corrsponding to attribute_name if it's an association
|
18
|
+
def [](attribute_name)
|
19
|
+
get_attribute(attribute_name) ||
|
20
|
+
get_association(attribute_name)
|
21
|
+
end
|
5
22
|
end
|
6
23
|
end
|
7
24
|
end
|
data/lib/her/model/http.rb
CHANGED
@@ -2,266 +2,82 @@ module Her
|
|
2
2
|
module Model
|
3
3
|
# This module interacts with Her::API to fetch HTTP data
|
4
4
|
module HTTP
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
# Automatically inherit a superclass' api
|
9
|
+
def her_api
|
10
|
+
@_her_api ||= begin
|
11
|
+
if superclass.respond_to?(:her_api)
|
12
|
+
superclass.her_api
|
13
|
+
else
|
14
|
+
Her::API.default_api
|
15
|
+
end
|
12
16
|
end
|
13
17
|
end
|
14
|
-
end
|
15
18
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
# Main request wrapper around Her::API. Used to make custom request to the API.
|
22
|
-
# @private
|
23
|
-
def request(attrs={})
|
24
|
-
request = her_api.request(attrs)
|
25
|
-
if block_given?
|
26
|
-
yield request[:parsed_data], request[:response]
|
27
|
-
else
|
28
|
-
{ :parsed_data => request[:parsed_data], :response => request[:response] }
|
19
|
+
# Link a model with a Her::API object
|
20
|
+
def uses_api(api)
|
21
|
+
@_her_api = api
|
29
22
|
end
|
30
|
-
end
|
31
23
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
# include Her::Model
|
37
|
-
# end
|
38
|
-
#
|
39
|
-
# @popular_users = User.get(:popular)
|
40
|
-
# # Fetched via GET "/users/popular"
|
41
|
-
def get(path, attrs={})
|
42
|
-
path = "#{build_request_path(attrs)}/#{path}" if path.is_a?(Symbol)
|
43
|
-
get_raw(path, attrs) do |parsed_data, response|
|
44
|
-
if parsed_data[:data].is_a?(Array)
|
45
|
-
new_collection(parsed_data)
|
46
|
-
else
|
47
|
-
new(parse(parsed_data[:data]).merge :_metadata => parsed_data[:data], :_errors => parsed_data[:errors])
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
24
|
+
# Main request wrapper around Her::API. Used to make custom request to the API.
|
25
|
+
# @private
|
26
|
+
def request(attrs={})
|
27
|
+
request = her_api.request(attrs)
|
51
28
|
|
52
|
-
|
53
|
-
|
54
|
-
path = "#{build_request_path(attrs)}/#{path}" if path.is_a?(Symbol)
|
55
|
-
request(attrs.merge(:_method => :get, :_path => path), &block)
|
56
|
-
end
|
57
|
-
|
58
|
-
# Make a GET request and return a collection of resources
|
59
|
-
def get_collection(path=nil, attrs={})
|
60
|
-
path = "#{build_request_path(attrs)}/#{path}" if path.is_a?(Symbol)
|
61
|
-
get_raw(path, attrs) do |parsed_data, response|
|
62
|
-
new_collection(parsed_data)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
# Make a GET request and return a collection of resources
|
67
|
-
def get_resource(path, attrs={})
|
68
|
-
path = "#{build_request_path(attrs)}/#{path}" if path.is_a?(Symbol)
|
69
|
-
get_raw(path, attrs) do |parsed_data, response|
|
70
|
-
new(parse(parsed_data[:data]).merge :_metadata => parsed_data[:data], :_errors => parsed_data[:errors])
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
# Make a POST request and return either a collection or a resource
|
75
|
-
def post(path, attrs={})
|
76
|
-
path = "#{build_request_path(attrs)}/#{path}" if path.is_a?(Symbol)
|
77
|
-
post_raw(path, attrs) do |parsed_data, response|
|
78
|
-
if parsed_data[:data].is_a?(Array)
|
79
|
-
new_collection(parsed_data)
|
29
|
+
if block_given?
|
30
|
+
yield request[:parsed_data], request[:response]
|
80
31
|
else
|
81
|
-
|
32
|
+
{ :parsed_data => request[:parsed_data], :response => request[:response] }
|
82
33
|
end
|
83
34
|
end
|
84
|
-
end
|
85
35
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
post_raw(path, attrs) do |parsed_data, response|
|
104
|
-
new(parse(parsed_data[:data]))
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
# Make a PUT request and return either a collection or a resource
|
109
|
-
def put(path, attrs={})
|
110
|
-
path = "#{build_request_path(attrs)}/#{path}" if path.is_a?(Symbol)
|
111
|
-
put_raw(path, attrs) do |parsed_data, response|
|
112
|
-
if parsed_data[:data].is_a?(Array)
|
113
|
-
new_collection(parsed_data)
|
114
|
-
else
|
115
|
-
new(parse(parsed_data[:data]).merge :_metadata => parsed_data[:data], :_errors => parsed_data[:errors])
|
36
|
+
# For each HTTP method, define these methods:
|
37
|
+
#
|
38
|
+
# - <method>(path, attrs)
|
39
|
+
# - <method>_raw(path, attrs, &block)
|
40
|
+
# - <method>_collection(path, attrs, &block)
|
41
|
+
# - <method>_resource(path, attrs, &block)
|
42
|
+
# - custom_<method>(path, attrs)
|
43
|
+
%w{GET POST PUT PATCH DELETE}.map(&:downcase).map(&:to_sym).each do |method|
|
44
|
+
define_method method do |path, attrs={}|
|
45
|
+
path = build_request_path_from_string_or_symbol(path, attrs)
|
46
|
+
send("#{method}_raw".to_sym, path, attrs) do |parsed_data, response|
|
47
|
+
if parsed_data[:data].is_a?(Array)
|
48
|
+
new_collection(parsed_data)
|
49
|
+
else
|
50
|
+
new(parse(parsed_data[:data]).merge :_metadata => parsed_data[:metadata], :_errors => parsed_data[:errors])
|
51
|
+
end
|
52
|
+
end
|
116
53
|
end
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
# Make a PUT request and return the parsed JSON response (not mapped to objects)
|
121
|
-
def put_raw(path, attrs={}, &block)
|
122
|
-
path = "#{build_request_path(attrs)}/#{path}" if path.is_a?(Symbol)
|
123
|
-
request(attrs.merge(:_method => :put, :_path => path), &block)
|
124
|
-
end
|
125
|
-
|
126
|
-
# Make a PUT request and return a collection of resources
|
127
|
-
def put_collection(path, attrs={})
|
128
|
-
path = "#{build_request_path(attrs)}/#{path}" if path.is_a?(Symbol)
|
129
|
-
put_raw(path, attrs) do |parsed_data, response|
|
130
|
-
new_collection(parsed_data)
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
# Make a PUT request and return a collection of resources
|
135
|
-
def put_resource(path, attrs={})
|
136
|
-
path = "#{build_request_path(attrs)}/#{path}" if path.is_a?(Symbol)
|
137
|
-
put_raw(path, attrs) do |parsed_data, response|
|
138
|
-
new(parse(parsed_data[:data]).merge :_metadata => parsed_data[:data], :_errors => parsed_data[:errors])
|
139
|
-
end
|
140
|
-
end
|
141
54
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
patch_raw(path, attrs) do |parsed_data, response|
|
146
|
-
if parsed_data[:data].is_a?(Array)
|
147
|
-
new_collection(parsed_data)
|
148
|
-
else
|
149
|
-
new(parse(parsed_data[:data]).merge :_metadata => parsed_data[:data], :_errors => parsed_data[:errors])
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
# Make a PATCH request and return the parsed JSON response (not mapped to objects)
|
155
|
-
def patch_raw(path, attrs={}, &block)
|
156
|
-
path = "#{build_request_path(attrs)}/#{path}" if path.is_a?(Symbol)
|
157
|
-
request(attrs.merge(:_method => :patch, :_path => path), &block)
|
158
|
-
end
|
159
|
-
|
160
|
-
# Make a PATCH request and return a collection of resources
|
161
|
-
def patch_collection(path, attrs={})
|
162
|
-
path = "#{build_request_path(attrs)}/#{path}" if path.is_a?(Symbol)
|
163
|
-
patch_raw(path, attrs) do |parsed_data, response|
|
164
|
-
new_collection(parsed_data)
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
# Make a PATCH request and return a collection of resources
|
169
|
-
def patch_resource(path, attrs={})
|
170
|
-
path = "#{build_request_path(attrs)}/#{path}" if path.is_a?(Symbol)
|
171
|
-
patch_raw(path, attrs) do |parsed_data, response|
|
172
|
-
new(parse(parsed_data[:data]).merge :_metadata => parsed_data[:data], :_errors => parsed_data[:errors])
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
# Make a DELETE request and return either a collection or a resource
|
177
|
-
def delete(path, attrs={})
|
178
|
-
path = "#{build_request_path(attrs)}/#{path}" if path.is_a?(Symbol)
|
179
|
-
delete_raw(path, attrs) do |parsed_data, response|
|
180
|
-
if parsed_data[:data].is_a?(Array)
|
181
|
-
new_collection(parsed_data)
|
182
|
-
else
|
183
|
-
new(parse(parsed_data[:data]).merge :_metadata => parsed_data[:data], :_errors => parsed_data[:errors])
|
184
|
-
end
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
|
-
# Make a DELETE request and return the parsed JSON response (not mapped to objects)
|
189
|
-
def delete_raw(path, attrs={}, &block)
|
190
|
-
path = "#{build_request_path(attrs)}/#{path}" if path.is_a?(Symbol)
|
191
|
-
request(attrs.merge(:_method => :delete, :_path => path), &block)
|
192
|
-
end
|
193
|
-
|
194
|
-
# Make a DELETE request and return a collection of resources
|
195
|
-
def delete_collection(path, attrs={})
|
196
|
-
path = "#{build_request_path(attrs)}/#{path}" if path.is_a?(Symbol)
|
197
|
-
delete_raw(path, attrs) do |parsed_data, response|
|
198
|
-
new_collection(parsed_data)
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
|
-
# Make a DELETE request and return a collection of resources
|
203
|
-
def delete_resource(path, attrs={})
|
204
|
-
path = "#{build_request_path(attrs)}/#{path}" if path.is_a?(Symbol)
|
205
|
-
delete_raw(path, attrs) do |parsed_data, response|
|
206
|
-
new(parse(parsed_data[:data]).merge :_metadata => parsed_data[:data], :_errors => parsed_data[:errors])
|
207
|
-
end
|
208
|
-
end
|
209
|
-
|
210
|
-
# Define custom GET requests
|
211
|
-
#
|
212
|
-
# @example
|
213
|
-
# class User
|
214
|
-
# include Her::Model
|
215
|
-
# custom_get :popular
|
216
|
-
# end
|
217
|
-
#
|
218
|
-
# User.popular
|
219
|
-
# # Fetched from GET "/users/popular"
|
220
|
-
def custom_get(*paths)
|
221
|
-
metaclass = (class << self; self; end)
|
222
|
-
paths.each do |path|
|
223
|
-
metaclass.send(:define_method, path.to_sym) do |*attrs|
|
224
|
-
get(path, attrs.first || Hash.new)
|
225
|
-
end
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
|
-
# Define custom POST requests
|
230
|
-
def custom_post(*paths)
|
231
|
-
metaclass = (class << self; self; end)
|
232
|
-
paths.each do |path|
|
233
|
-
metaclass.send(:define_method, path.to_sym) do |*attrs|
|
234
|
-
post(path, attrs.first || Hash.new)
|
55
|
+
define_method "#{method}_raw".to_sym do |path, attrs={}, &block|
|
56
|
+
path = build_request_path_from_string_or_symbol(path, attrs)
|
57
|
+
request(attrs.merge(:_method => method, :_path => path), &block)
|
235
58
|
end
|
236
|
-
end
|
237
|
-
end
|
238
59
|
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
put(path, attrs.first || Hash.new)
|
60
|
+
define_method "#{method}_collection".to_sym do |path=nil, attrs={}|
|
61
|
+
path = build_request_path_from_string_or_symbol(path, attrs)
|
62
|
+
send("#{method}_raw".to_sym, build_request_path_from_string_or_symbol(path, attrs), attrs) do |parsed_data, response|
|
63
|
+
new_collection(parsed_data)
|
64
|
+
end
|
245
65
|
end
|
246
|
-
end
|
247
|
-
end
|
248
66
|
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
patch(path, attrs.first || Hash.new)
|
67
|
+
define_method "#{method}_resource".to_sym do |path, attrs={}|
|
68
|
+
path = build_request_path_from_string_or_symbol(path, attrs)
|
69
|
+
send("#{method}_raw".to_sym, path, attrs) do |parsed_data, response|
|
70
|
+
new(parse(parsed_data[:data]).merge :_metadata => parsed_data[:metadata], :_errors => parsed_data[:errors])
|
71
|
+
end
|
255
72
|
end
|
256
|
-
end
|
257
|
-
end
|
258
73
|
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
74
|
+
define_method "custom_#{method}".to_sym do |*paths|
|
75
|
+
metaclass = (class << self; self; end)
|
76
|
+
paths.each do |path|
|
77
|
+
metaclass.send(:define_method, path.to_sym) do |*attrs|
|
78
|
+
send(method, path, attrs.first || Hash.new)
|
79
|
+
end
|
80
|
+
end
|
265
81
|
end
|
266
82
|
end
|
267
83
|
end
|