api-model 0.0.4 → 0.1.0
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 +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
|