yaks 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -2
- data/README.md +79 -23
- data/lib/yaks/collection_mapper.rb +7 -4
- data/lib/yaks/config.rb +2 -1
- data/lib/yaks/default_policy.rb +1 -1
- data/lib/yaks/mapper/has_many.rb +7 -0
- data/lib/yaks/mapper/has_one.rb +4 -0
- data/lib/yaks/null_resource.rb +8 -1
- data/lib/yaks/serializer/json_api.rb +4 -2
- data/lib/yaks/version.rb +1 -1
- data/spec/acceptance/acceptance_spec.rb +4 -4
- data/spec/acceptance/models.rb +19 -1
- data/spec/json/confucius.hal.json +29 -0
- data/spec/json/confucius.json_api.json +28 -2
- data/spec/spec_helper.rb +1 -0
- data/spec/support/deep_eql.rb +110 -0
- data/spec/yaml/confucius.yaml +18 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 40c42f259955a15a723d0782ab4378201bf511b3
|
4
|
+
data.tar.gz: 360a9de28a43b27cf820c26aec19c6627a7dac2b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5fb54a5b204c60f385aa4b8e4915c6fce1c89dcb1340b48323242c4ade3a4265d44a5ff37f5d587302cab90ad6e05003e160e290fe69b36f19285934d94f3faf
|
7
|
+
data.tar.gz: 5d4462422ddd28e6106846a8663fbdb43bf2ad33b302c24bdcc0f424edae60d1774455d0f70cd3041422aafdd6d0d6ee697558942026ac1bd84d66f149816748
|
data/CHANGELOG.md
CHANGED
@@ -1,10 +1,17 @@
|
|
1
|
+
# v0.4.1
|
2
|
+
|
3
|
+
* Change how env is passed to yaks.serialize to match docs
|
4
|
+
* Fix JSON-API bug (#18 reported by Nicolas Blanco)
|
5
|
+
* Don't pluralize has_one association names in JSON-API
|
6
|
+
|
1
7
|
# v0.4.0
|
2
8
|
|
3
9
|
* Introduce after {} post-processing hook
|
4
|
-
* Streamline interfaces and variable names
|
10
|
+
* Streamline interfaces and variable names, especially the use of `call`
|
5
11
|
* Improve deriving mappers automatically, even with Rails style autoloading
|
6
12
|
* Give CollectionResource a members_rel, for HAL-like formats with no top-level collection concept
|
7
|
-
* Switch back to using `src` and `dest` as the rel-template keys
|
13
|
+
* Switch back to using `src` and `dest` as the rel-template keys, instead of `association_name`
|
14
|
+
* deprecate `mapper_namespace` in favor of `namespace`
|
8
15
|
|
9
16
|
# v0.4.0.rc1
|
10
17
|
|
data/README.md
CHANGED
@@ -16,8 +16,6 @@
|
|
16
16
|
|
17
17
|
Yaks is a tool for turning your domain models into Hypermedia resources.
|
18
18
|
|
19
|
-
**If you're just starting out with Yaks it is currently recommended to run directly from master until 0.4.0 comes out.**
|
20
|
-
|
21
19
|
There are at the moment a number of competing media types for building Hypermedia APIs. These all add a layer of semantics on top of a low level serialization format such as JSON or XML. Even though they each have their own design goals, the core features mostly overlap. They typically provide a way to represent resources (entities), and resource collections, consisting of
|
22
20
|
|
23
21
|
* Data in key-value format, possibly with composite values
|
@@ -64,29 +62,13 @@ or a bit more elaborate
|
|
64
62
|
```ruby
|
65
63
|
yaks = Yaks.new do
|
66
64
|
default_format :json_api
|
67
|
-
rel_template 'http://api.example.com/rels/{
|
65
|
+
rel_template 'http://api.example.com/rels/{dest}'
|
68
66
|
format_options(:hal, plural_links: [:copyright])
|
69
67
|
end
|
70
68
|
|
71
69
|
yaks.serialize(post, mapper: PostMapper, format: :hal)
|
72
70
|
```
|
73
71
|
|
74
|
-
Yaks by default will find your mappers for you if they follow the naming convention of appending 'Mapper' to the model class name. This (and all other "conventions") can be easily redefined though, see below. If you have your mappers inside a module, use `mapper_namespace`.
|
75
|
-
|
76
|
-
```ruby
|
77
|
-
module API
|
78
|
-
module Mappers
|
79
|
-
class PostMapper < Yaks::Mapper
|
80
|
-
#...
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
yaks = Yaks.new do
|
86
|
-
mapper_namespace API::Mappers
|
87
|
-
end
|
88
|
-
```
|
89
|
-
|
90
72
|
### Attributes
|
91
73
|
|
92
74
|
Use the `attributes` DSL method to specify which attributes of your model you want to expose, as in the example above. You can override the `load_attribute` method to change how attributes are fetched from the model.
|
@@ -178,6 +160,80 @@ Options
|
|
178
160
|
* `:collection_mapper` : For mapping the collection as a whole, this defaults to Yaks::CollectionMapper, but you can subclass it for example to add links or attributes on the collection itself
|
179
161
|
* `:rel` : Set the relation (symbol or URI) this association has with the object. Will be derived from the association name and the configured rel_template if ommitted
|
180
162
|
|
163
|
+
## Namespace
|
164
|
+
|
165
|
+
Yaks by default will find your mappers for you if they follow the naming convention of appending 'Mapper' to the model class name. This (and all other "conventions") can be easily redefined though, see below. If you have your mappers inside a module, use `namespace`.
|
166
|
+
|
167
|
+
```ruby
|
168
|
+
module API
|
169
|
+
module Mappers
|
170
|
+
class PostMapper < Yaks::Mapper
|
171
|
+
#...
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
yaks = Yaks.new do
|
177
|
+
namespace API::Mappers
|
178
|
+
end
|
179
|
+
```
|
180
|
+
|
181
|
+
If your namespace contains a `CollectionMapper`, Yaks will use that instead of `Yaks::CollectionMapper`, e.g.
|
182
|
+
|
183
|
+
```ruby
|
184
|
+
module API
|
185
|
+
module Mappers
|
186
|
+
class CollectionMapper < Yaks::CollectionMapper
|
187
|
+
link :profile, 'http://api.example.com/profiles/collection'
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
```
|
192
|
+
|
193
|
+
You can also have collection mappers based on the type of members the collection holds, e.g.
|
194
|
+
|
195
|
+
```ruby
|
196
|
+
module API
|
197
|
+
module Mappers
|
198
|
+
class LineItemCollectionMapper < Yaks::CollectionMapper
|
199
|
+
link :profile, 'http://api.example.com/profiles/line_items'
|
200
|
+
attributes :total
|
201
|
+
|
202
|
+
def total
|
203
|
+
collection.inject(0) do |memo, line_item|
|
204
|
+
memo + line_item.price * line_item.quantity
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
```
|
211
|
+
|
212
|
+
Yaks will automatically detect and use this collection when serializing an array of `LineItem` objects.
|
213
|
+
|
214
|
+
## Rack env
|
215
|
+
|
216
|
+
When serializing, Yaks lets you pass in an `env` hash, which will be made available to all mappers.
|
217
|
+
|
218
|
+
```ruby
|
219
|
+
yaks = Yaks.new
|
220
|
+
yaks.serialize(foo, env: my_env)
|
221
|
+
|
222
|
+
class FooMapper
|
223
|
+
attributes :bar
|
224
|
+
|
225
|
+
def bar
|
226
|
+
if env['something']
|
227
|
+
#...
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
```
|
232
|
+
|
233
|
+
You can use this to pass around context, in particular context related to the current HTTP request, e.g. the current logged in user, which is why the recommended use is to pass in the Rack environment.
|
234
|
+
|
235
|
+
If `env` contains a `HTTP_ACCEPT` key (Rack's way of representing the `Accept` header), Yaks will return the format that most closely matches what was requested.
|
236
|
+
|
181
237
|
## Custom attribute/link/subresource handling
|
182
238
|
|
183
239
|
When inheriting from `Yaks::Mapper`, you can override `map_attributes`, `map_links` and `map_resources` to skip (or augment) above methods, and instead implement your own custom mechanism. For example
|
@@ -320,8 +376,8 @@ For JSON based formats, a final step in serializing is to turn the nested data i
|
|
320
376
|
|
321
377
|
```ruby
|
322
378
|
Yaks.new do
|
323
|
-
map_to_primitive Date, Time, DateTime do
|
324
|
-
|
379
|
+
map_to_primitive Date, Time, DateTime do |date|
|
380
|
+
date.iso8601
|
325
381
|
end
|
326
382
|
end
|
327
383
|
```
|
@@ -330,8 +386,8 @@ This can also be used to transform alternative data structures, like those from
|
|
330
386
|
|
331
387
|
```ruby
|
332
388
|
Yaks.new do
|
333
|
-
map_to_primitive Hamster::Vector, Hamster::List do
|
334
|
-
|
389
|
+
map_to_primitive Hamster::Vector, Hamster::List do |list|
|
390
|
+
list.map do |item|
|
335
391
|
call(item)
|
336
392
|
end
|
337
393
|
end
|
@@ -20,21 +20,24 @@ module Yaks
|
|
20
20
|
def call(collection)
|
21
21
|
@object = collection
|
22
22
|
|
23
|
-
|
23
|
+
attrs = {
|
24
24
|
type: collection_type,
|
25
|
-
members_rel: members_rel,
|
26
25
|
links: map_links,
|
27
26
|
attributes: map_attributes,
|
28
27
|
members: collection.map do |obj|
|
29
28
|
mapper_for_model(obj).new(context).call(obj)
|
30
29
|
end
|
31
|
-
|
30
|
+
}
|
31
|
+
|
32
|
+
attrs[ :members_rel ] = members_rel if members_rel
|
33
|
+
|
34
|
+
CollectionResource.new(attrs)
|
32
35
|
end
|
33
36
|
|
34
37
|
private
|
35
38
|
|
36
39
|
def members_rel
|
37
|
-
policy.expand_rel( 'collection', pluralize( collection_type ) )
|
40
|
+
policy.expand_rel( 'collection', pluralize( collection_type ) ) if collection_type
|
38
41
|
end
|
39
42
|
|
40
43
|
def collection_type
|
data/lib/yaks/config.rb
CHANGED
data/lib/yaks/default_policy.rb
CHANGED
@@ -38,7 +38,7 @@ module Yaks
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def derive_mapper_from_association(association)
|
41
|
-
@options[:namespace].const_get("#{camelize(
|
41
|
+
@options[:namespace].const_get("#{camelize(association.singular_name)}Mapper")
|
42
42
|
end
|
43
43
|
|
44
44
|
def derive_rel_from_association(mapper, association)
|
data/lib/yaks/mapper/has_many.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
module Yaks
|
2
2
|
class Mapper
|
3
3
|
class HasMany < Association
|
4
|
+
include Util
|
5
|
+
|
4
6
|
def map_resource(collection, context)
|
7
|
+
return NullResource.new(collection: true) if collection.nil?
|
5
8
|
policy = context.fetch(:policy)
|
6
9
|
member_mapper = association_mapper(policy)
|
7
10
|
context = context.merge(member_mapper: member_mapper)
|
@@ -12,6 +15,10 @@ module Yaks
|
|
12
15
|
return @collection_mapper unless @collection_mapper.equal? Undefined
|
13
16
|
policy.derive_mapper_from_object(collection)
|
14
17
|
end
|
18
|
+
|
19
|
+
def singular_name
|
20
|
+
singularize(name.to_s)
|
21
|
+
end
|
15
22
|
end
|
16
23
|
end
|
17
24
|
end
|
data/lib/yaks/mapper/has_one.rb
CHANGED
data/lib/yaks/null_resource.rb
CHANGED
@@ -2,6 +2,10 @@ module Yaks
|
|
2
2
|
class NullResource
|
3
3
|
include Enumerable
|
4
4
|
|
5
|
+
def initialize(opts = {})
|
6
|
+
@collection = opts.fetch(:collection, false)
|
7
|
+
end
|
8
|
+
|
5
9
|
def each
|
6
10
|
return to_enum unless block_given?
|
7
11
|
end
|
@@ -21,8 +25,11 @@ module Yaks
|
|
21
25
|
def [](*)
|
22
26
|
end
|
23
27
|
|
28
|
+
def type
|
29
|
+
end
|
30
|
+
|
24
31
|
def collection?
|
25
|
-
|
32
|
+
@collection
|
26
33
|
end
|
27
34
|
end
|
28
35
|
end
|
@@ -29,7 +29,9 @@ module Yaks
|
|
29
29
|
|
30
30
|
def serialize_links(subresources)
|
31
31
|
subresources.each_with_object({}) do |(name, resource), hsh|
|
32
|
-
|
32
|
+
next if resource.is_a? NullResource
|
33
|
+
key = resource.collection? ? pluralize(resource.type) : resource.type
|
34
|
+
hsh[key] = serialize_link(resource)
|
33
35
|
end
|
34
36
|
end
|
35
37
|
|
@@ -53,7 +55,7 @@ module Yaks
|
|
53
55
|
def serialize_subresource(resource, linked)
|
54
56
|
key = pluralize(resource.type)
|
55
57
|
set = linked.fetch(key) { Set.new }
|
56
|
-
linked
|
58
|
+
linked[key] = (set << serialize_resource(resource))
|
57
59
|
serialize_linked_subresources(resource.subresources, linked)
|
58
60
|
end
|
59
61
|
end
|
data/lib/yaks/version.rb
CHANGED
@@ -3,12 +3,12 @@ require 'spec_helper'
|
|
3
3
|
require_relative './models'
|
4
4
|
|
5
5
|
RSpec.shared_examples_for 'JSON output format' do |yaks, format, name|
|
6
|
-
let(:input) { load_yaml_fixture
|
6
|
+
let(:input) { load_yaml_fixture(name) }
|
7
7
|
let(:output) { load_json_fixture "#{name}.#{format}" }
|
8
8
|
|
9
9
|
subject { yaks.serialize(input) }
|
10
10
|
|
11
|
-
it { should
|
11
|
+
it { should deep_eql output }
|
12
12
|
end
|
13
13
|
|
14
14
|
RSpec.describe Yaks::Serializer::Hal do
|
@@ -22,8 +22,8 @@ RSpec.describe Yaks::Serializer::Hal do
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
include_examples 'JSON output format' , yaks_rel_template
|
26
|
-
include_examples 'JSON output format' , yaks_policy_dsl
|
25
|
+
include_examples 'JSON output format' , yaks_rel_template , :hal , 'confucius'
|
26
|
+
include_examples 'JSON output format' , yaks_policy_dsl , :hal , 'confucius'
|
27
27
|
end
|
28
28
|
|
29
29
|
RSpec.describe Yaks::Serializer::JsonApi do
|
data/spec/acceptance/models.rb
CHANGED
@@ -5,7 +5,15 @@ class Scholar
|
|
5
5
|
end
|
6
6
|
|
7
7
|
class Work
|
8
|
-
include Anima.new(:id, :chinese_name, :english_name)
|
8
|
+
include Anima.new(:id, :chinese_name, :english_name, :quotes, :era)
|
9
|
+
end
|
10
|
+
|
11
|
+
class Quote
|
12
|
+
include Anima.new(:id, :chinese, :english, :sources)
|
13
|
+
end
|
14
|
+
|
15
|
+
class Era
|
16
|
+
include Anima.new(:id, :name)
|
9
17
|
end
|
10
18
|
|
11
19
|
class LiteratureBaseMapper < Yaks::Mapper
|
@@ -25,4 +33,14 @@ end
|
|
25
33
|
|
26
34
|
class WorkMapper < LiteratureBaseMapper
|
27
35
|
attributes :id, :chinese_name, :english_name
|
36
|
+
has_many :quotes
|
37
|
+
has_one :era
|
38
|
+
end
|
39
|
+
|
40
|
+
class QuoteMapper < Yaks::Mapper
|
41
|
+
attributes :id, :chinese
|
42
|
+
end
|
43
|
+
|
44
|
+
class EraMapper < Yaks::Mapper
|
45
|
+
attributes :id, :name
|
28
46
|
end
|
@@ -16,6 +16,35 @@
|
|
16
16
|
"_links": {
|
17
17
|
"self": { "href": "http://literature.example.com/work/11" },
|
18
18
|
"profile": { "href": "http://literature.example.com/profiles/work" }
|
19
|
+
},
|
20
|
+
"_embedded": {
|
21
|
+
"http://literature.example.com/rel/quotes": [
|
22
|
+
{
|
23
|
+
"id": 17,
|
24
|
+
"chinese": "廄焚。子退朝,曰:“傷人乎?” 不問馬。"
|
25
|
+
},
|
26
|
+
{
|
27
|
+
"id": 18,
|
28
|
+
"chinese": "子曰:“其恕乎!己所不欲、勿施於人。”"
|
29
|
+
}
|
30
|
+
],
|
31
|
+
"http://literature.example.com/rel/era": {
|
32
|
+
"id": 99,
|
33
|
+
"name": "Zhou Dynasty"
|
34
|
+
}
|
35
|
+
}
|
36
|
+
},
|
37
|
+
{
|
38
|
+
"id": 12,
|
39
|
+
"chinese_name": "易經",
|
40
|
+
"english_name": "Commentaries to the Yi-jing",
|
41
|
+
"_links": {
|
42
|
+
"self": { "href": "http://literature.example.com/work/12" },
|
43
|
+
"profile": { "href": "http://literature.example.com/profiles/work" }
|
44
|
+
},
|
45
|
+
"_embedded": {
|
46
|
+
"http://literature.example.com/rel/quotes": [],
|
47
|
+
"http://literature.example.com/rel/era": null
|
19
48
|
}
|
20
49
|
}
|
21
50
|
]
|
@@ -6,7 +6,7 @@
|
|
6
6
|
"pinyin": "Kongzi",
|
7
7
|
"latinized": "Confucius",
|
8
8
|
"links": {
|
9
|
-
"works": [11]
|
9
|
+
"works": [11,12]
|
10
10
|
}
|
11
11
|
}
|
12
12
|
],
|
@@ -15,7 +15,33 @@
|
|
15
15
|
{
|
16
16
|
"id": 11,
|
17
17
|
"chinese_name": "論語",
|
18
|
-
"english_name": "Analects"
|
18
|
+
"english_name": "Analects",
|
19
|
+
"links": {
|
20
|
+
"quotes": [17, 18],
|
21
|
+
"era": 99
|
22
|
+
}
|
23
|
+
},
|
24
|
+
{
|
25
|
+
"id": 12,
|
26
|
+
"chinese_name": "易經",
|
27
|
+
"english_name": "Commentaries to the Yi-jing",
|
28
|
+
"links": {}
|
29
|
+
}
|
30
|
+
],
|
31
|
+
"quotes": [
|
32
|
+
{
|
33
|
+
"id": 17,
|
34
|
+
"chinese": "廄焚。子退朝,曰:“傷人乎?” 不問馬。"
|
35
|
+
},
|
36
|
+
{
|
37
|
+
"id": 18,
|
38
|
+
"chinese": "子曰:“其恕乎!己所不欲、勿施於人。”"
|
39
|
+
}
|
40
|
+
],
|
41
|
+
"erae": [
|
42
|
+
{
|
43
|
+
"id": 99,
|
44
|
+
"name": "Zhou Dynasty"
|
19
45
|
}
|
20
46
|
]
|
21
47
|
}
|
data/spec/spec_helper.rb
CHANGED
@@ -0,0 +1,110 @@
|
|
1
|
+
# When comparing deep nested structures, it can be really hard to figure out what
|
2
|
+
# the actual differences are looking at the RSpec output. This custom matcher
|
3
|
+
# traverses nested hashes and arrays recursively, and reports each difference
|
4
|
+
# separately, with a JSONPath string of where the difference was found
|
5
|
+
#
|
6
|
+
# e.g.
|
7
|
+
#
|
8
|
+
# at $.shows[0].venues[0].name, got Foo, expected Bar
|
9
|
+
|
10
|
+
module Matchers
|
11
|
+
class DeepEql
|
12
|
+
extend Forwardable
|
13
|
+
attr_reader :expectation, :stack, :target, :diffs, :result
|
14
|
+
def_delegators :stack, :push, :pop
|
15
|
+
|
16
|
+
def initialize(expectation, stack = [], diffs = [])
|
17
|
+
@expectation = expectation
|
18
|
+
@stack = stack
|
19
|
+
@diffs = diffs
|
20
|
+
@result = true
|
21
|
+
end
|
22
|
+
|
23
|
+
def description
|
24
|
+
'be deeply equal'
|
25
|
+
end
|
26
|
+
|
27
|
+
def recurse(target, expectation)
|
28
|
+
@result &&= DeepEql.new(expectation, stack, diffs).matches?(target)
|
29
|
+
end
|
30
|
+
|
31
|
+
def stack_as_jsonpath
|
32
|
+
'$' + stack.map do |item|
|
33
|
+
case item
|
34
|
+
when Integer, /\W/
|
35
|
+
"[#{item.inspect}]"
|
36
|
+
else
|
37
|
+
".#{item}"
|
38
|
+
end
|
39
|
+
end.join
|
40
|
+
end
|
41
|
+
|
42
|
+
def failure_message(message)
|
43
|
+
diffs << "at %s, %s" % [stack_as_jsonpath, message]
|
44
|
+
@result = false
|
45
|
+
end
|
46
|
+
|
47
|
+
def compare(key)
|
48
|
+
push key
|
49
|
+
if target[key] != expectation[key]
|
50
|
+
if [Hash, Array].any?{|klz| target[key].is_a? klz }
|
51
|
+
recurse(target[key], expectation[key])
|
52
|
+
else
|
53
|
+
failure_message begin
|
54
|
+
if expectation[key].class == target[key].class
|
55
|
+
"expected #{expectation[key].inspect}, got #{target[key].inspect}"
|
56
|
+
else
|
57
|
+
"expected #{expectation[key].class}: #{expectation[key].inspect}, got #{target[key].class}: #{target[key].inspect}"
|
58
|
+
end
|
59
|
+
rescue Encoding::CompatibilityError
|
60
|
+
"expected #{expectation[key].encoding}, got #{target[key].encoding}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
pop
|
65
|
+
end
|
66
|
+
|
67
|
+
def matches?(target)
|
68
|
+
@target = target
|
69
|
+
|
70
|
+
case expectation
|
71
|
+
when Hash
|
72
|
+
if target.is_a?(Hash)
|
73
|
+
if target.class != expectation.class # e.g. HashWithIndifferentAccess
|
74
|
+
failure_message("expected #{expectation.class}, got #{target.class}")
|
75
|
+
end
|
76
|
+
(target.keys | expectation.keys).each do |key|
|
77
|
+
compare key
|
78
|
+
end
|
79
|
+
else
|
80
|
+
failure_message("expected Hash got #{@target.inspect}")
|
81
|
+
end
|
82
|
+
|
83
|
+
when Array
|
84
|
+
if target.is_a?(Array)
|
85
|
+
0.upto([target.count, expectation.count].max) do |idx|
|
86
|
+
compare idx
|
87
|
+
end
|
88
|
+
else
|
89
|
+
failure_message("expected Array got #{@target.inspect}")
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
result
|
94
|
+
end
|
95
|
+
|
96
|
+
def failure_message_for_should
|
97
|
+
diffs.join("\n")
|
98
|
+
end
|
99
|
+
|
100
|
+
def failure_message_for_should_not
|
101
|
+
"expected #{@target.inspect} not to be in deep_eql with #{@expectation.inspect}"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
module RSpec::Matchers
|
107
|
+
def deep_eql(exp)
|
108
|
+
Matchers::DeepEql.new(exp)
|
109
|
+
end
|
110
|
+
end
|
data/spec/yaml/confucius.yaml
CHANGED
@@ -8,3 +8,21 @@ works:
|
|
8
8
|
id: 11
|
9
9
|
chinese_name: "論語"
|
10
10
|
english_name: "Analects"
|
11
|
+
era: !ruby/object:Era
|
12
|
+
id: 99
|
13
|
+
name: "Zhou Dynasty"
|
14
|
+
quotes:
|
15
|
+
- !ruby/object:Quote
|
16
|
+
id: 17
|
17
|
+
chinese: "廄焚。子退朝,曰:“傷人乎?” 不問馬。"
|
18
|
+
english: "When the stables were burnt down, on returning from court Confucius said, “Was anyone hurt?” He did not ask about the horses."
|
19
|
+
sources: "Analects X.11 (tr. Waley), 10–13 (tr. Legge), or X-17 (tr. Lau)"
|
20
|
+
- !ruby/object:Quote
|
21
|
+
id: 18
|
22
|
+
chinese: "子曰:“其恕乎!己所不欲、勿施於人。”"
|
23
|
+
english: "The Master replied: “How about 'reciprocity'! Never impose on others what you would not choose for yourself.”"
|
24
|
+
sources: "Analects XV.24, tr. David Hinton"
|
25
|
+
- !ruby/object:Work
|
26
|
+
id: 12
|
27
|
+
chinese_name: "易經"
|
28
|
+
english_name: "Commentaries to the Yi-jing"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yaks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arne Brasseur
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-06-
|
11
|
+
date: 2014-06-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: inflection
|
@@ -219,6 +219,7 @@ files:
|
|
219
219
|
- spec/json/john.hal.json
|
220
220
|
- spec/json/youtypeitwepostit.collection.json
|
221
221
|
- spec/spec_helper.rb
|
222
|
+
- spec/support/deep_eql.rb
|
222
223
|
- spec/support/fixtures.rb
|
223
224
|
- spec/support/friends_mapper.rb
|
224
225
|
- spec/support/models.rb
|
@@ -280,6 +281,7 @@ test_files:
|
|
280
281
|
- spec/json/john.hal.json
|
281
282
|
- spec/json/youtypeitwepostit.collection.json
|
282
283
|
- spec/spec_helper.rb
|
284
|
+
- spec/support/deep_eql.rb
|
283
285
|
- spec/support/fixtures.rb
|
284
286
|
- spec/support/friends_mapper.rb
|
285
287
|
- spec/support/models.rb
|