yaks 0.4.4 → 0.5.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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/CHANGELOG.md +44 -3
  4. data/README.md +90 -33
  5. data/Rakefile +10 -0
  6. data/bench/bench.rb +0 -1
  7. data/bench/bench_1000.rb +60 -0
  8. data/lib/yaks/breaking_changes.rb +22 -0
  9. data/lib/yaks/config/dsl.rb +114 -27
  10. data/lib/yaks/config.rb +39 -54
  11. data/lib/yaks/default_policy.rb +32 -14
  12. data/lib/yaks/format/collection_json.rb +4 -4
  13. data/lib/yaks/format/hal.rb +20 -3
  14. data/lib/yaks/format/json_api.rb +3 -3
  15. data/lib/yaks/format.rb +54 -9
  16. data/lib/yaks/fp/callable.rb +9 -0
  17. data/lib/yaks/fp/hash_updatable.rb +2 -0
  18. data/lib/yaks/fp/updatable.rb +2 -0
  19. data/lib/yaks/fp.rb +8 -0
  20. data/lib/yaks/mapper/link.rb +2 -2
  21. data/lib/yaks/mapper.rb +6 -6
  22. data/lib/yaks/primitivize.rb +2 -2
  23. data/lib/yaks/resource/link.rb +0 -4
  24. data/lib/yaks/runner.rb +90 -0
  25. data/lib/yaks/util.rb +4 -0
  26. data/lib/yaks/version.rb +1 -1
  27. data/lib/yaks.rb +3 -0
  28. data/spec/acceptance/acceptance_spec.rb +6 -1
  29. data/spec/json/confucius.collection.json +5 -16
  30. data/spec/json/plant_collection.collection.json +32 -0
  31. data/spec/spec_helper.rb +2 -1
  32. data/spec/support/deep_eql.rb +14 -7
  33. data/spec/support/pet_mapper.rb +0 -2
  34. data/spec/unit/yaks/collection_mapper_spec.rb +24 -2
  35. data/spec/unit/yaks/config/dsl_spec.rb +6 -10
  36. data/spec/unit/yaks/config_spec.rb +40 -99
  37. data/spec/unit/yaks/default_policy_spec.rb +20 -0
  38. data/spec/unit/yaks/format/collection_json_spec.rb +41 -0
  39. data/spec/unit/yaks/format/hal_spec.rb +38 -3
  40. data/spec/unit/yaks/format/json_api_spec.rb +2 -2
  41. data/spec/unit/yaks/format_spec.rb +28 -3
  42. data/spec/unit/yaks/fp/callable_spec.rb +13 -0
  43. data/spec/unit/yaks/mapper_spec.rb +226 -126
  44. data/spec/unit/yaks/resource/link_spec.rb +2 -3
  45. data/spec/unit/yaks/resource_spec.rb +15 -0
  46. data/spec/unit/yaks/runner_spec.rb +260 -0
  47. data/spec/unit/yaks/util_spec.rb +7 -1
  48. data/yaks.gemspec +4 -1
  49. metadata +72 -15
  50. /data/spec/json/{hal_plant_collection.json → plant_collection.hal.json} +0 -0
@@ -8,23 +8,19 @@ module Yaks
8
8
  namespace: Kernel
9
9
  }
10
10
 
11
- # @!attribute [r] options
11
+ # @!attribute [r]
12
12
  # @return [Hash]
13
13
  attr_reader :options
14
14
 
15
- # @param [Hash] options
16
- # @return [Yaks::DefaultPolicy]
15
+ # @param options [Hash] options
17
16
  def initialize(options = {})
18
17
  @options = DEFAULTS.merge(options)
19
18
  end
20
19
 
21
- # @param [Object] model
22
- # @return [Yaks::CollectionMapper, Yaks::Mapper]
23
- # or a subclass of Yaks::Mapper of some sort.
24
- #
25
- # @raise [NameError] only occurs when the model
26
- # is anything but a collection.
20
+ # @param model [Object]
21
+ # @return [Class] A mapper, typically a subclass of Yaks::Mapper
27
22
  #
23
+ # @raise [NameError] only occurs when the model is anything but a collection.
28
24
  def derive_mapper_from_object(model)
29
25
  if model.respond_to? :to_ary
30
26
  if m = model.first
@@ -45,14 +41,28 @@ module Yaks
45
41
  end
46
42
  end
47
43
 
48
- # @param [Class] mapper_class
44
+ # Derive the a mapper type name
45
+ #
46
+ # This returns the 'system name' for a mapper,
47
+ # e.g. ShowEventMapper => show_event.
48
+ #
49
+ # @param [Class] mapper_class
50
+ #
49
51
  # @return [String]
50
52
  def derive_type_from_mapper_class(mapper_class)
51
53
  underscore(mapper_class.name.split('::').last.sub(/Mapper$/, ''))
52
54
  end
53
55
 
54
- # @param [Yaks::Mapper::Association] association
55
- # @return [Class] of subclass Yaks::Mapper
56
+ # Derive the mapper type name from a collection
57
+ #
58
+ # This inspects the first element of the collection, so it
59
+ # requires a non-empty collection. Will return nil if the
60
+ # collection is empty.
61
+ #
62
+ # @param [#first] collection
63
+ #
64
+ # @return [String|nil]
65
+ #
56
66
  # @raise [NameError]
57
67
  def derive_type_from_collection(collection)
58
68
  if collection.any?
@@ -66,16 +76,24 @@ module Yaks
66
76
  @options[:namespace].const_get("#{camelize(association.singular_name)}Mapper")
67
77
  end
68
78
 
69
- # @param [Yaks::Mapper::Association] association
79
+ # @param association [Yaks::Mapper::Association]
70
80
  # @return [String]
71
81
  def derive_rel_from_association(association)
72
82
  expand_rel( association.name )
73
83
  end
74
84
 
75
- # @param [String] relname
85
+ # @param relname [String]
76
86
  # @return [String]
77
87
  def expand_rel(relname)
78
88
  URITemplate.new(@options[:rel_template]).expand(rel: relname)
79
89
  end
90
+
91
+ # @param format_class [Class]
92
+ # @return [#call] format_class
93
+ def serializer_for_format(format_class)
94
+ {
95
+ json: JSON.method(:pretty_generate)
96
+ }.fetch(format_class.serializer)
97
+ end
80
98
  end
81
99
  end
@@ -1,11 +1,11 @@
1
1
  module Yaks
2
2
  class Format
3
3
  class CollectionJson < self
4
- Format.register self, :collection_json, 'application/vnd.collection+json'
4
+ register :collection_json, :json, 'application/vnd.collection+json'
5
5
 
6
6
  include FP
7
7
 
8
- # @param [Yaks:Resource] resource
8
+ # @param [Yaks::Resource] resource
9
9
  # @return [Hash]
10
10
  def serialize_resource(resource)
11
11
  result = {
@@ -29,10 +29,10 @@ module Yaks
29
29
  result = { data: attrs }
30
30
  result[:href] = item.self_link.uri if item.self_link
31
31
  item.links.each do |link|
32
- next if link.rel == :self
32
+ next if link.rel.equal? :self
33
33
  result[:links] = [] unless result.key?(:links)
34
34
  result[:links] << {rel: link.rel, href: link.uri}
35
- result[:links].last[:name] = link.name if link.name
35
+ result[:links].last[:name] = link.title if link.title
36
36
  end
37
37
  result
38
38
  end
@@ -2,8 +2,26 @@
2
2
 
3
3
  module Yaks
4
4
  class Format
5
+ # Hypertext Application Language (http://stateless.co/hal_specification.html)
6
+ #
7
+ # A lightweight JSON Hypermedia message format.
8
+ #
9
+ # Options: +:plural_links+ In HAL, a single rel can correspond to
10
+ # a single link, or to a list of links. Which rels are singular
11
+ # and which are plural is application-dependant. Yaks assumes all
12
+ # links are singular. If your resource might contain multiple
13
+ # links for the same rel, then configure that rel to be plural. In
14
+ # that case it will always be rendered as a collection, even when
15
+ # the resource only contains a single link.
16
+ #
17
+ # @example
18
+ #
19
+ # yaks = Yaks.new do
20
+ # format_options :hal, {plural_links: [:related_content]}
21
+ # end
22
+ #
5
23
  class Hal < self
6
- Format.register self, :hal, 'application/hal+json'
24
+ register :hal, :json, 'application/hal+json'
7
25
 
8
26
  protected
9
27
 
@@ -14,7 +32,6 @@ module Yaks
14
32
  # looking at client behavior (Hyperagent) it seems safer to return an empty
15
33
  # resource.
16
34
  #
17
- # return nil if resource.is_a? NullResource
18
35
  result = resource.attributes
19
36
  result = result.merge(:_links => serialize_links(resource.links)) unless resource.links.empty?
20
37
  result = result.merge(:_embedded => serialize_embedded(resource.subresources)) unless resource.subresources.empty?
@@ -37,7 +54,7 @@ module Yaks
37
54
  memo[link.rel] = if singular?(link.rel)
38
55
  hal_link
39
56
  else
40
- Array(memo[link.rel]) + [hal_link]
57
+ (memo[link.rel] || []) + [hal_link]
41
58
  end
42
59
  memo
43
60
  end
@@ -2,8 +2,8 @@
2
2
 
3
3
  module Yaks
4
4
  class Format
5
- class JsonApi < self
6
- Format.register self, :json_api, 'application/vnd.api+json'
5
+ class JsonAPI < self
6
+ register :json_api, :json, 'application/vnd.api+json'
7
7
 
8
8
  include FP
9
9
 
@@ -40,7 +40,7 @@ module Yaks
40
40
  # @return [Hash]
41
41
  def serialize_links(subresources)
42
42
  subresources.each_with_object({}) do |(_name, resource), hsh|
43
- next if resource.is_a? NullResource
43
+ next if resource.instance_of? NullResource
44
44
  key = resource.collection? ? pluralize(resource.type) : resource.type
45
45
  hsh[key] = serialize_link(resource)
46
46
  end
data/lib/yaks/format.rb CHANGED
@@ -2,40 +2,85 @@ module Yaks
2
2
  class Format
3
3
  extend Forwardable
4
4
  include Util
5
+ include FP::Callable
5
6
 
7
+ # @!attribute [r] options
8
+ # @return [Hash]
6
9
  attr_reader :options
10
+
7
11
  def_delegators :resource, :links, :attributes, :subresources
8
12
 
9
13
  protected :links, :attributes, :subresources, :options
10
14
 
15
+ # @param [Hash] options
16
+ # @return [Hash]
11
17
  def initialize(options = {})
12
18
  @options = options
13
19
  end
14
20
 
21
+ # @param [Yaks::Resource] resource
22
+ # @return [Hash]
15
23
  def call(resource)
16
24
  serialize_resource(resource)
17
25
  end
18
26
  alias serialize call
19
27
 
20
28
  class << self
21
- def register(klass, name, mime_type)
22
- @formats ||= {}
23
- @formats[name] = klass
29
+ attr_reader :format_name, :serializer, :mime_type
30
+
31
+ def all
32
+ @formats ||= []
33
+ end
24
34
 
25
- @mime_types ||= {}
26
- @mime_types[mime_type] = [name, klass]
35
+ # @param [Constant] klass
36
+ # @param [Symbol] format_name
37
+ # @param [String] mime_type
38
+ # @return [Array]
39
+ def register(format_name, serializer, mime_type)
40
+ @format_name = format_name
41
+ @serializer = serializer
42
+ @mime_type = mime_type
43
+
44
+ Format.all << self
27
45
  end
28
46
 
29
- def by_name(name)
30
- @formats.fetch(name)
47
+ # @param [Symbol] format_name
48
+ # @return [Constant]
49
+ # @raise [KeyError]
50
+ def by_name(format_name)
51
+ find(:format_name, format_name)
31
52
  end
32
53
 
54
+ # @param [Symbol] mime_type
55
+ # @return [Constant]
56
+ # @raise [KeyError]
33
57
  def by_mime_type(mime_type)
34
- @mime_types.fetch(mime_type)[1]
58
+ find(:mime_type, mime_type)
59
+ end
60
+
61
+ def by_accept_header(accept_header)
62
+ mime_type = Rack::Accept::Charset.new(accept_header).best_of(mime_types.values)
63
+ if mime_type
64
+ by_mime_type(mime_type)
65
+ else
66
+ yield if block_given?
67
+ end
35
68
  end
36
69
 
37
70
  def mime_types
38
- @mime_types.inject({}) {|memo, (mime_type, (name, _))| memo[name] = mime_type ; memo }
71
+ Format.all.each_with_object({}) do
72
+ |format, memo| memo[format.format_name] = format.mime_type
73
+ end
74
+ end
75
+
76
+ def names
77
+ mime_types.keys
78
+ end
79
+
80
+ private
81
+
82
+ def find(key, cond)
83
+ Format.all.detect {|format| format.send(key) == cond }
39
84
  end
40
85
  end
41
86
  end
@@ -0,0 +1,9 @@
1
+ module Yaks
2
+ module FP
3
+ module Callable
4
+ def to_proc
5
+ method(:call).to_proc
6
+ end
7
+ end
8
+ end
9
+ end
@@ -2,6 +2,8 @@ module Yaks
2
2
  module FP
3
3
 
4
4
  class HashUpdatable < Module
5
+ # @param [Array] attributes
6
+ # @return [Symbol]
5
7
  def initialize(*attributes)
6
8
  define_method :update do |updates|
7
9
  self.class.new(
@@ -2,6 +2,8 @@ module Yaks
2
2
  module FP
3
3
 
4
4
  class Updatable < Module
5
+ # @param [Array] attributes
6
+ # @return [Symbol]
5
7
  def initialize(*attributes)
6
8
  define_method :update do |updates|
7
9
  self.class.new(
data/lib/yaks/fp.rb CHANGED
@@ -2,15 +2,23 @@ module Yaks
2
2
  module FP
3
3
  extend self
4
4
 
5
+ # @param [Symbol, String] name
6
+ # @return [Proc]
5
7
  def curry_method(name)
6
8
  method(name).to_proc.curry
7
9
  end
8
10
 
11
+
12
+ # @return [Proc]
9
13
  def identity_function
10
14
  ->(x) {x}
11
15
  end
12
16
  I = identity_function
13
17
 
18
+ # @param [Symbol] symbol
19
+ # @param [Array] args
20
+ # @param [Proc] blk
21
+ # @return [Proc]
14
22
  def send_with_args(symbol, *args, &blk)
15
23
  ->(obj) { obj.method(symbol).(*args, &blk) }
16
24
  end
@@ -57,7 +57,7 @@ module Yaks
57
57
  end
58
58
 
59
59
  def expansion_mapping(lookup)
60
- template_variables.map.with_object({}) do |name, hsh|
60
+ template_variables.each_with_object({}) do |name, hsh|
61
61
  hsh[name] = lookup[name]
62
62
  end
63
63
  end
@@ -74,7 +74,7 @@ module Yaks
74
74
  end
75
75
 
76
76
  def expand_with(lookup)
77
- return lookup[template] if template.is_a? Symbol
77
+ return lookup[template] if template.instance_of? Symbol
78
78
 
79
79
  expand_partial(expansion_mapping(lookup)).to_s
80
80
  end
data/lib/yaks/mapper.rb CHANGED
@@ -55,20 +55,20 @@ module Yaks
55
55
  private
56
56
 
57
57
  def map_attributes(resource)
58
- attributes.inject(resource) do |resource, attribute|
59
- attribute.add_to_resource(resource, self, context)
58
+ attributes.inject(resource) do |res, attribute|
59
+ attribute.add_to_resource(res, self, context)
60
60
  end
61
61
  end
62
62
 
63
63
  def map_links(resource)
64
- links.inject(resource) do |resource, mapper_link|
65
- mapper_link.add_to_resource(resource, self, context)
64
+ links.inject(resource) do |res, mapper_link|
65
+ mapper_link.add_to_resource(res, self, context)
66
66
  end
67
67
  end
68
68
 
69
69
  def map_subresources(resource)
70
- associations.inject(resource) do |resource, association|
71
- association.add_to_resource( resource, self, context)
70
+ associations.inject(resource) do |res, association|
71
+ association.add_to_resource(res, self, context)
72
72
  end
73
73
  end
74
74
  end
@@ -22,7 +22,7 @@ module Yaks
22
22
 
23
23
  def self.create
24
24
  new.tap do |p|
25
- p.map String, TrueClass, FalseClass, NilClass, Numeric do |object|
25
+ p.map String, Numeric, true, false, nil do |object|
26
26
  object
27
27
  end
28
28
 
@@ -31,7 +31,7 @@ module Yaks
31
31
  end
32
32
 
33
33
  p.map Hash do |object|
34
- object.to_enum(:each).with_object({}) do |(key, value), output|
34
+ object.to_enum.with_object({}) do |(key, value), output|
35
35
  output[call(key)] = call(value)
36
36
  end
37
37
  end
@@ -9,10 +9,6 @@ module Yaks
9
9
  @rel, @uri, @options = rel, uri, options
10
10
  end
11
11
 
12
- def name
13
- options[:name]
14
- end
15
-
16
12
  def title
17
13
  options[:title]
18
14
  end
@@ -0,0 +1,90 @@
1
+ module Yaks
2
+ class Runner
3
+ include Util
4
+ include Anima.new(:object, :config, :options)
5
+ include Adamantium::Flat
6
+ extend Forwardable
7
+
8
+ def_delegators :config, :policy, :default_format, :format_options, :primitivize, :serializers, :hooks
9
+
10
+ def call
11
+ steps.inject(object) {|memo, (_, step)| step.call(memo) }
12
+ end
13
+
14
+ def context
15
+ {
16
+ policy: policy,
17
+ env: env,
18
+ mapper_stack: []
19
+ }.merge(slice_hash(options, :item_mapper))
20
+ end
21
+ memoize :context, freezer: :flat
22
+
23
+ def env
24
+ options.fetch(:env, {})
25
+ end
26
+ memoize :env, freezer: :noop
27
+
28
+ # @return [Class]
29
+ def format_class
30
+ Format.by_accept_header(env['HTTP_ACCEPT']) {
31
+ Format.by_name(options.fetch(:format) { default_format })
32
+ }
33
+ end
34
+ memoize :format_class
35
+
36
+ def steps
37
+ insert_hooks(
38
+ [[ :map, mapper ],
39
+ [ :format, formatter ],
40
+ [ :primitivize, primitivize], # really a JSON-preprocessor, should be pulled out
41
+ [ :serialize, serializer ]])
42
+ end
43
+ memoize :steps
44
+
45
+ def mapper
46
+ options.fetch(:mapper) do
47
+ policy.derive_mapper_from_object(object)
48
+ end.new(context)
49
+ end
50
+ memoize :mapper, freezer: :noop
51
+
52
+ def formatter
53
+ format_class.new(format_options[format_name])
54
+ end
55
+ memoize :formatter
56
+
57
+ # @param [Hash] opts
58
+ # @return [String]
59
+ def format_name
60
+ options.fetch(:format) { default_format }
61
+ end
62
+ memoize :format_name
63
+
64
+ def serializer
65
+ serializers.fetch(format_class.serializer) do
66
+ policy.serializer_for_format(format_class)
67
+ end
68
+ end
69
+ memoize :serializer
70
+
71
+ def insert_hooks(steps)
72
+ hooks.inject(steps) do |steps, (type, target_step, name, hook)|
73
+ steps.flat_map do |step_name, callable|
74
+ if step_name.eql? target_step
75
+ case type
76
+ when :before
77
+ [[name, hook], [step_name, callable]]
78
+ when :after
79
+ [[step_name, callable], [name, hook]]
80
+ when :around
81
+ [[step_name, ->(x) { hook.call(x, &callable) }]]
82
+ when :skip
83
+ []
84
+ end
85
+ end || [[step_name, callable]]
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
data/lib/yaks/util.rb CHANGED
@@ -18,6 +18,10 @@ module Yaks
18
18
  .gsub!(/(?:^|_)(.)/) { $1.upcase }
19
19
  end
20
20
 
21
+ def slice_hash(hash, *keys)
22
+ keys.each_with_object({}) {|k,dest| dest[k] = hash[k] if hash.key?(k) }
23
+ end
24
+
21
25
  # Turn what is maybe a Proc into its result (or itself)
22
26
  #
23
27
  # When input can be either a value or a proc that returns a value,
data/lib/yaks/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Yaks
2
- VERSION = '0.4.4'
2
+ VERSION = '0.5.0'
3
3
  end
data/lib/yaks.rb CHANGED
@@ -4,6 +4,7 @@ require 'forwardable'
4
4
  require 'set'
5
5
  require 'pathname'
6
6
 
7
+ require 'anima'
7
8
  require 'concord'
8
9
  require 'inflection'
9
10
  require 'uri_template'
@@ -13,6 +14,7 @@ require 'yaks/util'
13
14
  require 'yaks/fp'
14
15
  require 'yaks/fp/updatable'
15
16
  require 'yaks/fp/hash_updatable'
17
+ require 'yaks/fp/callable'
16
18
  require 'yaks/primitivize'
17
19
 
18
20
  require 'yaks/default_policy'
@@ -57,3 +59,4 @@ require 'yaks/format/collection_json'
57
59
 
58
60
  require 'yaks/config/dsl'
59
61
  require 'yaks/config'
62
+ require 'yaks/runner'
@@ -7,6 +7,7 @@ RSpec.describe Yaks::Format::Hal do
7
7
  yaks_rel_template = Yaks.new do
8
8
  format_options :hal, plural_links: ['http://literature.example.com/rels/quotes']
9
9
  rel_template "http://literature.example.com/rel/{association_name}"
10
+ skip :serialize
10
11
  end
11
12
 
12
13
  yaks_policy_dsl = Yaks.new do
@@ -14,15 +15,17 @@ RSpec.describe Yaks::Format::Hal do
14
15
  derive_rel_from_association do |association|
15
16
  "http://literature.example.com/rel/#{association.name}"
16
17
  end
18
+ skip :serialize
17
19
  end
18
20
 
19
21
  include_examples 'JSON output format' , yaks_rel_template , :hal , 'confucius'
20
22
  include_examples 'JSON output format' , yaks_policy_dsl , :hal , 'confucius'
21
23
  end
22
24
 
23
- RSpec.describe Yaks::Format::JsonApi do
25
+ RSpec.describe Yaks::Format::JsonAPI do
24
26
  config = Yaks.new do
25
27
  default_format :json_api
28
+ skip :serialize
26
29
  end
27
30
 
28
31
  include_examples 'JSON output format' , config , :json_api , 'confucius'
@@ -32,10 +35,12 @@ RSpec.describe Yaks::Format::CollectionJson do
32
35
  youtypeit_yaks = Yaks.new do
33
36
  default_format :collection_json
34
37
  namespace Youtypeitwepostit
38
+ skip :serialize
35
39
  end
36
40
 
37
41
  confucius_yaks = Yaks.new do
38
42
  default_format :collection_json
43
+ skip :serialize
39
44
  end
40
45
 
41
46
  include_examples 'JSON output format', youtypeit_yaks, :collection, 'youtypeitwepostit'
@@ -6,22 +6,10 @@
6
6
  {
7
7
  "href": "http://literature.example.com/authors/kongzi",
8
8
  "data": [
9
- {
10
- "name": "id",
11
- "value": 9
12
- },
13
- {
14
- "name": "name",
15
- "value": "孔子"
16
- },
17
- {
18
- "name": "pinyin",
19
- "value": "Kongzi"
20
- },
21
- {
22
- "name": "latinized",
23
- "value": "Confucius"
24
- }
9
+ { "name": "id", "value": 9 },
10
+ { "name": "name", "value": "孔子" },
11
+ { "name": "pinyin", "value": "Kongzi" },
12
+ { "name": "latinized", "value": "Confucius" }
25
13
  ],
26
14
  "links": [
27
15
  {
@@ -29,6 +17,7 @@
29
17
  "href": "http://literature.example.com/profiles/scholar"
30
18
  },
31
19
  {
20
+ "name": "Search for quotes",
32
21
  "rel": "http://literature.example.com/rels/quotes",
33
22
  "href": "http://literature.example.com/quotes/?author=kongzi&q={query}"
34
23
  }
@@ -0,0 +1,32 @@
1
+ {
2
+ "collection": {
3
+ "version": "1.0",
4
+ "href": "http://api.example.com/plants",
5
+ "items": [
6
+ {
7
+ "href": "http://api.example.com/plants/7/plain_grass",
8
+ "data": [ { "name": "name", "value": "Plain grass" },
9
+ { "name": "type", "value": "grass" } ],
10
+ "links": [
11
+ { "rel": "profile", "href": "http://api.example.com/doc/plant" }
12
+ ]
13
+ },
14
+ {
15
+ "href": "http://api.example.com/plants/15/oak",
16
+ "data": [ { "name": "name", "value": "Oak" },
17
+ { "name": "type", "value": "tree" } ],
18
+ "links": [
19
+ { "rel": "profile", "href": "http://api.example.com/doc/plant" }
20
+ ]
21
+ },
22
+ {
23
+ "href": "http://api.example.com/plants/33/passiflora",
24
+ "data": [ { "name": "name", "value": "Passiflora" },
25
+ { "name": "type", "value": "flower" } ],
26
+ "links": [
27
+ { "rel": "profile", "href": "http://api.example.com/doc/plant" }
28
+ ]
29
+ }
30
+ ]
31
+ }
32
+ }
data/spec/spec_helper.rb CHANGED
@@ -20,10 +20,11 @@ require_relative 'support/classes_for_policy_testing'
20
20
  RSpec.configure do |rspec|
21
21
  rspec.include FixtureHelpers
22
22
  rspec.backtrace_exclusion_patterns = [] if ENV['FULLSTACK']
23
- #rspec.disable_monkey_patching!
23
+ rspec.disable_monkey_patching!
24
24
  rspec.raise_errors_for_deprecations!
25
25
  end
26
26
 
27
27
  Bogus.configure do |bogus|
28
28
  bogus.search_modules << Yaks
29
+ bogus.search_modules << Yaks::Mapper
29
30
  end