api-model 0.0.4 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +23 -5
- data/api-model.gemspec +1 -1
- data/lib/api-model.rb +4 -11
- data/lib/api_model/{rest_methods.rb → class_methods.rb} +1 -1
- data/lib/api_model/instance_methods.rb +28 -0
- data/spec/api-model/api_model_spec.rb +21 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b4468bee16f23aca5211838b3f54b918a0340716
|
4
|
+
data.tar.gz: 27a2004bc4145a4e6c71e3ae87c703b092b0c7d3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dcfae89dae5eb342dd14c6992efdd94cb2bff77582d2ede112bc3446a129225a1dd0025c4783bb7425bbe95c04518eca6e8f5d53d3a7bc2d177b994adfb45eeb
|
7
|
+
data.tar.gz: 6028927509a5e087babd8ad3f01d37819928a2bc39651c49a16c862bb77ea9b85c861d14560faf6f62d7b74fd69c3ec04cc04d76b35923958386c352488387cf
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -30,7 +30,7 @@ Then, let's say the API endpoint /foo returned JSON which looks like `{ "name":
|
|
30
30
|
Request types and params
|
31
31
|
------------------------
|
32
32
|
|
33
|
-
There's a couple of convenience methods to make it simpler to send GET and POST requests,
|
33
|
+
There's a couple of convenience methods to make it simpler to send GET and POST requests,
|
34
34
|
or you can send other request types:
|
35
35
|
|
36
36
|
```ruby
|
@@ -114,11 +114,29 @@ use as a builder should respond to `#build`, with the instance hash as an argume
|
|
114
114
|
MyModel.get_json "/foo", { some_param: "bar" }, builder: MyCustomBuilder.new
|
115
115
|
```
|
116
116
|
|
117
|
+
Handling validation errors in responses
|
118
|
+
---------------------------------------
|
119
|
+
|
120
|
+
ApiModel uses a bunch of Rails' ActiveModel enhancements to make it easy to use things such as validation errors.
|
121
|
+
You can define validations in the normal ActiveModel::Validations style and check validity before posting
|
122
|
+
to external APIs should you wish to. Or, if an external API returns errors which you would like to convert to
|
123
|
+
ActiveModel validations, you can do that, too:
|
124
|
+
|
125
|
+
```ruby
|
126
|
+
class Car
|
127
|
+
property :name
|
128
|
+
end
|
129
|
+
|
130
|
+
car = Car.new
|
131
|
+
car.set_errors_from_hash name: "cannot be blank"
|
132
|
+
car.errors[:name] # => ["cannot be blank"]
|
133
|
+
```
|
134
|
+
|
117
135
|
Configuring API Model
|
118
136
|
---------------------
|
119
137
|
|
120
138
|
You can configure API model in a number of places; globally using `ApiModel::Base.api_config`, per-model
|
121
|
-
using `MyModel.api_config`, and per-api call by passing in options in the options hash (although some
|
139
|
+
using `MyModel.api_config`, and per-api call by passing in options in the options hash (although some
|
122
140
|
configuration options may not be available on the per-api call technique).
|
123
141
|
|
124
142
|
### API Host
|
@@ -141,7 +159,7 @@ to refer to the full url all the time.
|
|
141
159
|
```
|
142
160
|
|
143
161
|
If the API response which you receive is deeply nested and you want to cut out some levels of nesting, you
|
144
|
-
can use `json_root` to set which key objects should be built from.
|
162
|
+
can use `json_root` to set which key objects should be built from.
|
145
163
|
|
146
164
|
You can dig down multiple levels by separating keys with a period. With the example above, say the server
|
147
165
|
was returning JSON which looked like `{"data":{"posts":{"name":"Foo"}}}`, it would behave as if the
|
@@ -201,12 +219,12 @@ something like this:
|
|
201
219
|
```ruby
|
202
220
|
class MyCustomCacheStrategy
|
203
221
|
attr_accessor :id, :options
|
204
|
-
|
222
|
+
|
205
223
|
def initialize(id, options)
|
206
224
|
@id = id
|
207
225
|
@options = options
|
208
226
|
end
|
209
|
-
|
227
|
+
|
210
228
|
def cache(&block)
|
211
229
|
# here you can check whether you want to actually call the api by running
|
212
230
|
# block.call, or want to find and return your cached response.
|
data/api-model.gemspec
CHANGED
@@ -2,7 +2,7 @@ $:.push File.expand_path("../lib", __FILE__)
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = "api-model"
|
5
|
-
s.version = "0.0
|
5
|
+
s.version = "0.1.0"
|
6
6
|
s.authors = ["Damien Timewell"]
|
7
7
|
s.email = ["mail@damientimewell.com"]
|
8
8
|
s.homepage = "https://github.com/iZettle/api-model"
|
data/lib/api-model.rb
CHANGED
@@ -8,7 +8,8 @@ require 'ostruct'
|
|
8
8
|
require 'api_model/initializer'
|
9
9
|
require 'api_model/http_request'
|
10
10
|
require 'api_model/response'
|
11
|
-
require 'api_model/
|
11
|
+
require 'api_model/class_methods'
|
12
|
+
require 'api_model/instance_methods'
|
12
13
|
require 'api_model/configuration'
|
13
14
|
require 'api_model/cache_stategies/no_cache'
|
14
15
|
require 'api_model/response_parser/json'
|
@@ -36,17 +37,9 @@ module ApiModel
|
|
36
37
|
extend ActiveModel::Naming
|
37
38
|
extend ActiveModel::Callbacks
|
38
39
|
|
39
|
-
extend
|
40
|
+
extend ClassMethods
|
40
41
|
include ConfigurationMethods
|
41
|
-
|
42
|
-
# Overrides Hashie::Trash to catch errors from trying to set properties which have not been defined
|
43
|
-
# and defines it automatically
|
44
|
-
def property_exists?(property_name)
|
45
|
-
super property_name
|
46
|
-
rescue NoMethodError
|
47
|
-
Log.debug "Could not set #{property_name} on #{self.class.name}. Defining it now."
|
48
|
-
self.class.property property_name.to_sym
|
49
|
-
end
|
42
|
+
include InstanceMethods
|
50
43
|
end
|
51
44
|
|
52
45
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module ApiModel
|
2
|
+
module InstanceMethods
|
3
|
+
|
4
|
+
# Overrides Hashie::Trash to catch errors from trying to set properties which have not been defined
|
5
|
+
# and defines it automatically
|
6
|
+
def property_exists?(property_name)
|
7
|
+
super property_name
|
8
|
+
rescue NoMethodError
|
9
|
+
Log.debug "Could not set #{property_name} on #{self.class.name}. Defining it now."
|
10
|
+
self.class.property property_name.to_sym
|
11
|
+
end
|
12
|
+
|
13
|
+
# Convenience method to handle error hashes and set them as ActiveModel errors on instances.
|
14
|
+
# Using the `obj`, you can move the errors on to child classes if needed.
|
15
|
+
def set_errors_from_hash(errors_hash, obj = self)
|
16
|
+
errors_hash.each do |field,messages|
|
17
|
+
if messages.is_a?(Array)
|
18
|
+
messages.each do |message|
|
19
|
+
obj.errors.add field.to_sym, message
|
20
|
+
end
|
21
|
+
else
|
22
|
+
obj.errors.add field.to_sym, messages
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -127,6 +127,27 @@ describe ApiModel do
|
|
127
127
|
end
|
128
128
|
end
|
129
129
|
|
130
|
+
describe "setting errors from a hash" do
|
131
|
+
let(:car) { Car.new }
|
132
|
+
let(:blog_post) { BlogPost.new }
|
133
|
+
|
134
|
+
it 'should assign errors from a simple hash using active model errors' do
|
135
|
+
car.set_errors_from_hash name: "Is invalid"
|
136
|
+
car.errors[:name].should eq ["Is invalid"]
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'should assign multiple errors from an array' do
|
140
|
+
car.set_errors_from_hash top_speed: ["is too fast", "would break the sound barrier"]
|
141
|
+
car.errors[:top_speed].size.should eq 2
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'should be possible to assign the errors to other classes' do
|
145
|
+
car.set_errors_from_hash({ name: "is bad" }, blog_post)
|
146
|
+
car.errors.size.should eq 0
|
147
|
+
blog_post.errors[:name].should eq ["is bad"]
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
130
151
|
describe "cache_id" do
|
131
152
|
it 'should use options and the request path to create an identifier for the cache' do
|
132
153
|
BlogPost.cache_id("/box", params: { foo: "bar" }).should eq "/boxfoobar"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: api-model
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Damien Timewell
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-01-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -140,12 +140,13 @@ files:
|
|
140
140
|
- api-model.gemspec
|
141
141
|
- lib/api-model.rb
|
142
142
|
- lib/api_model/cache_stategies/no_cache.rb
|
143
|
+
- lib/api_model/class_methods.rb
|
143
144
|
- lib/api_model/configuration.rb
|
144
145
|
- lib/api_model/http_request.rb
|
145
146
|
- lib/api_model/initializer.rb
|
147
|
+
- lib/api_model/instance_methods.rb
|
146
148
|
- lib/api_model/response.rb
|
147
149
|
- lib/api_model/response_parser/json.rb
|
148
|
-
- lib/api_model/rest_methods.rb
|
149
150
|
- spec/api-model/api_model_spec.rb
|
150
151
|
- spec/api-model/configuration_spec.rb
|
151
152
|
- spec/api-model/http_request_spec.rb
|