yaks 0.3.1 → 0.4.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +11 -0
  4. data/Gemfile +0 -2
  5. data/LICENSE +7 -0
  6. data/README.md +160 -35
  7. data/Rakefile +2 -1
  8. data/lib/yaks/collection_mapper.rb +25 -18
  9. data/lib/yaks/collection_resource.rb +11 -17
  10. data/lib/yaks/config.rb +96 -0
  11. data/lib/yaks/default_policy.rb +34 -4
  12. data/lib/yaks/fp.rb +18 -0
  13. data/lib/yaks/mapper/association.rb +19 -27
  14. data/lib/yaks/mapper/class_methods.rb +4 -2
  15. data/lib/yaks/mapper/config.rb +24 -39
  16. data/lib/yaks/mapper/has_many.rb +7 -6
  17. data/lib/yaks/mapper/has_one.rb +4 -3
  18. data/lib/yaks/mapper/link.rb +52 -55
  19. data/lib/yaks/mapper.rb +38 -26
  20. data/lib/yaks/null_resource.rb +3 -3
  21. data/lib/yaks/primitivize.rb +29 -27
  22. data/lib/yaks/resource/link.rb +4 -0
  23. data/lib/yaks/resource.rb +18 -7
  24. data/lib/yaks/serializer/collection_json.rb +38 -0
  25. data/lib/yaks/serializer/hal.rb +55 -0
  26. data/lib/yaks/serializer/json_api.rb +61 -0
  27. data/lib/yaks/serializer.rb +25 -4
  28. data/lib/yaks/util.rb +2 -42
  29. data/lib/yaks/version.rb +1 -1
  30. data/lib/yaks.rb +10 -32
  31. data/notes.org +72 -0
  32. data/shaved_yak.gif +0 -0
  33. data/spec/acceptance/acceptance_spec.rb +46 -0
  34. data/spec/acceptance/models.rb +28 -0
  35. data/spec/integration/map_to_resource_spec.rb +11 -15
  36. data/spec/json/confucius.hal.json +23 -0
  37. data/spec/json/confucius.json_api.json +22 -0
  38. data/spec/json/john.hal.json +29 -0
  39. data/spec/json/youtypeitwepostit.collection.json +45 -0
  40. data/spec/spec_helper.rb +12 -1
  41. data/spec/support/shared_contexts.rb +7 -10
  42. data/spec/support/youtypeit_models_mappers.rb +20 -0
  43. data/spec/unit/yaks/collection_mapper_spec.rb +84 -0
  44. data/spec/unit/yaks/collection_resource_spec.rb +72 -0
  45. data/spec/unit/yaks/config_spec.rb +129 -0
  46. data/spec/unit/yaks/fp_spec.rb +31 -0
  47. data/spec/unit/yaks/mapper/association_spec.rb +80 -0
  48. data/spec/{yaks → unit/yaks}/mapper/class_methods_spec.rb +4 -4
  49. data/spec/unit/yaks/mapper/config_spec.rb +191 -0
  50. data/spec/unit/yaks/mapper/has_many_spec.rb +46 -0
  51. data/spec/unit/yaks/mapper/has_one_spec.rb +34 -0
  52. data/spec/unit/yaks/mapper/link_spec.rb +152 -0
  53. data/spec/unit/yaks/mapper_spec.rb +177 -0
  54. data/spec/unit/yaks/resource_spec.rb +40 -0
  55. data/spec/{yaks/hal_serializer_spec.rb → unit/yaks/serializer/hal_spec.rb} +2 -2
  56. data/spec/unit/yaks/serializer_spec.rb +12 -0
  57. data/spec/unit/yaks/util_spec.rb +43 -0
  58. data/spec/yaml/confucius.yaml +10 -0
  59. data/spec/yaml/youtypeitwepostit.yaml +9 -0
  60. data/yaks.gemspec +7 -8
  61. metadata +92 -53
  62. data/Gemfile.lock +0 -111
  63. data/lib/yaks/hal_serializer.rb +0 -59
  64. data/lib/yaks/json_api_serializer.rb +0 -59
  65. data/lib/yaks/link_lookup.rb +0 -23
  66. data/lib/yaks/mapper/lookup.rb +0 -19
  67. data/lib/yaks/mapper/map_links.rb +0 -17
  68. data/lib/yaks/profile_registry.rb +0 -60
  69. data/lib/yaks/rel_registry.rb +0 -20
  70. data/lib/yaks/shared_options.rb +0 -15
  71. data/spec/support/shorthands.rb +0 -22
  72. data/spec/yaks/collection_resource_spec.rb +0 -9
  73. data/spec/yaks/mapper/association_spec.rb +0 -21
  74. data/spec/yaks/mapper/config_spec.rb +0 -77
  75. data/spec/yaks/mapper/has_one_spec.rb +0 -16
  76. data/spec/yaks/mapper/link_spec.rb +0 -38
  77. data/spec/yaks/mapper/map_links_spec.rb +0 -46
  78. data/spec/yaks/mapper_spec.rb +0 -65
  79. data/spec/yaks/resource_spec.rb +0 -23
@@ -0,0 +1,55 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Yaks
4
+ class Serializer
5
+ class Hal < self
6
+ Serializer.register self, :hal, 'application/hal+json'
7
+
8
+ protected
9
+
10
+ def serialize_resource(resource)
11
+ # The HAL spec doesn't say explicitly how to deal missing values,
12
+ # looking at client behavior (Hyperagent) it seems safer to return an empty
13
+ # resource.
14
+ #
15
+ # return nil if resource.is_a? NullResource
16
+ result = resource.attributes
17
+ result = result.merge(:_links => serialize_links(resource.links)) unless resource.links.empty?
18
+ result = result.merge(:_embedded => serialize_embedded(resource.subresources)) unless resource.subresources.empty?
19
+ result
20
+ end
21
+
22
+ def serialize_links(links)
23
+ links.reduce({}, &method(:serialize_link))
24
+ end
25
+
26
+ def serialize_link(memo, link)
27
+ hal_link = {href: link.uri}
28
+ hal_link.merge!(link.options.reject{|k,_| k==:templated})
29
+ hal_link.merge!(templated: true) if link.templated?
30
+
31
+ memo[link.rel] = if singular?(link.rel)
32
+ hal_link
33
+ else
34
+ Array(memo[link.rel]) + [hal_link]
35
+ end
36
+ memo
37
+ end
38
+
39
+ def singular?(rel)
40
+ !options.fetch(:plural_links) { [] }.include?(rel)
41
+ end
42
+
43
+ def serialize_embedded(subresources)
44
+ subresources.each_with_object({}) do |(rel, resources), memo|
45
+ memo[rel] = if resources.collection?
46
+ resources.map( &method(:serialize_resource) )
47
+ else
48
+ serialize_resource(resources)
49
+ end
50
+ end
51
+ end
52
+
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,61 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Yaks
4
+ class Serializer
5
+ class JsonApi < self
6
+ Serializer.register self, :json_api, 'application/vnd.api+json'
7
+
8
+ include FP
9
+
10
+ def call
11
+ serialized = {
12
+ pluralize(resource.type) => resource.map(&method(:serialize_resource))
13
+ }
14
+
15
+ linked = resource.each_with_object({}) do |res, hsh|
16
+ serialize_linked_subresources(res.subresources, hsh)
17
+ end
18
+ serialized = serialized.merge('linked' => linked)
19
+
20
+ serialized
21
+ end
22
+ alias serialize call
23
+
24
+ def serialize_resource(resource)
25
+ result = resource.attributes
26
+ result = result.merge(:links => serialize_links(resource.subresources)) unless resource.subresources.empty?
27
+ result
28
+ end
29
+
30
+ def serialize_links(subresources)
31
+ subresources.each_with_object({}) do |(name, resource), hsh|
32
+ hsh[pluralize(resource.type)] = serialize_link(resource)
33
+ end
34
+ end
35
+
36
+ def serialize_link(resource)
37
+ resource.collection? ? resource.map(&send_with_args(:[], :id)) : resource[:id]
38
+ end
39
+
40
+ def serialize_linked_subresources(subresources, hsh)
41
+ subresources.each_with_object(hsh) do |(name, resources), hsh|
42
+ serialize_linked_resources(resources, hsh)
43
+ end
44
+ end
45
+
46
+ def serialize_linked_resources(resources, linked)
47
+ resources.each_with_object(linked) do |resource, memo|
48
+ serialize_subresource(resource, memo)
49
+ end
50
+ end
51
+
52
+ # {shows => [{id: 3, name: 'foo'}]}
53
+ def serialize_subresource(resource, linked)
54
+ key = pluralize(resource.type)
55
+ set = linked.fetch(key) { Set.new }
56
+ linked = linked[key] = (set << serialize_resource(resource))
57
+ serialize_linked_subresources(resource.subresources, linked)
58
+ end
59
+ end
60
+ end
61
+ end
@@ -1,7 +1,7 @@
1
1
  module Yaks
2
2
  class Serializer
3
3
  extend Forwardable
4
- include Util, SharedOptions
4
+ include Util
5
5
 
6
6
  attr_reader :resource, :options
7
7
  def_delegators :resource, :links, :attributes, :subresources
@@ -13,10 +13,31 @@ module Yaks
13
13
  @options = YAKS_DEFAULT_OPTIONS.merge(options)
14
14
  end
15
15
 
16
- def profile_name
17
- (profile = resource.profile) &&
18
- profile_registry.find_by_uri(profile)
16
+ def call
17
+ serialize_resource(resource)
19
18
  end
19
+ alias serialize call
20
20
 
21
+ class << self
22
+ def register(klass, name, mime_type)
23
+ @serializers ||= {}
24
+ @serializers[name] = klass
25
+
26
+ @mime_types ||= {}
27
+ @mime_types[mime_type] = klass
28
+ end
29
+
30
+ def by_name(name)
31
+ @serializers.fetch(name)
32
+ end
33
+
34
+ def by_mime_type(mime_type)
35
+ @mime_types.fetch(mime_type)
36
+ end
37
+
38
+ def mime_types
39
+ @mime_types.keys
40
+ end
41
+ end
21
42
  end
22
43
  end
data/lib/yaks/util.rb CHANGED
@@ -18,18 +18,6 @@ module Yaks
18
18
  .gsub!(/(?:^|_)(.)/) { $1.upcase }
19
19
  end
20
20
 
21
- def List(*args)
22
- Hamster.list(*args)
23
- end
24
-
25
- def Hash(*args)
26
- Hamster.hash(*args)
27
- end
28
-
29
- def Set(*args)
30
- Hamster.set(*args)
31
- end
32
-
33
21
  # Turn what is maybe a Proc into its result (or itself)
34
22
  #
35
23
  # When input can be either a value or a proc that returns a value,
@@ -44,9 +32,9 @@ module Yaks
44
32
  # @param [Object] context
45
33
  # (optional) A context used to instance_eval the proc
46
34
  def Resolve(maybe_proc, context = nil)
47
- if maybe_proc.respond_to?(:to_proc)
35
+ if maybe_proc.is_a? Proc or maybe_proc.is_a? Method
48
36
  if context
49
- if maybe_proc.to_proc.arity > 0
37
+ if maybe_proc.arity > 0
50
38
  context.instance_eval(&maybe_proc)
51
39
  else
52
40
  # In case it's a lambda with zero arity instance_eval fails
@@ -60,33 +48,5 @@ module Yaks
60
48
  end
61
49
  end
62
50
 
63
- def curry_method(name)
64
- method(name).to_proc.curry
65
- end
66
- alias μ curry_method
67
-
68
- def identity_function
69
- ->(x) {x}
70
- end
71
- alias ι identity_function
72
-
73
- def juxt(*procs)
74
- ->(*args) { procs.map &σ(:call, *args) }
75
- end
76
-
77
- def curry_symbol(symbol, *args, &blk)
78
- ->(obj) { obj.method(symbol).to_proc.curry.(*args, &blk) }
79
- end
80
- alias σ curry_symbol
81
- alias send_with_args curry_symbol
82
-
83
- def extract_options(args)
84
- if args.last.is_a? Hash
85
- [args.take(args.count-1), args.last]
86
- else
87
- [args, {}]
88
- end
89
- end
90
-
91
51
  end
92
52
  end
data/lib/yaks/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Yaks
2
- VERSION = '0.3.1'
2
+ VERSION = '0.4.0.rc1'
3
3
  end
data/lib/yaks.rb CHANGED
@@ -1,54 +1,31 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  require 'forwardable'
4
+ require 'set'
4
5
 
5
- require 'hamster'
6
6
  require 'concord'
7
7
  require 'inflection'
8
8
  require 'uri_template'
9
+ require 'rack/accept'
9
10
 
10
11
  require 'yaks/util'
11
- require 'yaks/link_lookup'
12
- require 'yaks/shared_options'
12
+ require 'yaks/fp'
13
13
  require 'yaks/primitivize'
14
14
 
15
- require 'yaks/profile_registry'
16
- require 'yaks/rel_registry'
17
15
  require 'yaks/default_policy'
18
16
 
19
17
  module Yaks
20
18
  Undefined = Object.new
21
19
 
22
20
  YAKS_DEFAULT_OPTIONS = {
23
- policy: DefaultPolicy.new,
24
- profile_registry: NullProfileRegistry.new,
25
- rel_registry: NullRelRegistry.new,
26
21
  singular_links: [:self, :profile]
27
22
  }
28
23
 
29
- module ClassMethods
30
- def Hash(object = nil)
31
- return object if object.is_a? Hamster::Hash
32
- return Hamster::EmptyHash if object.nil?
33
- Hamster.hash(object)
34
- end
35
-
36
- def List(*entries)
37
- case entries.size
38
- when 0
39
- Hamster::EmptyList
40
- when 1
41
- if entries.first.respond_to? :to_list
42
- entries.first.to_list
43
- else
44
- Hamster.list(*entries.compact)
45
- end
46
- else
47
- Hamster.list(*entries)
48
- end
24
+ class << self
25
+ def new(&blk)
26
+ Yaks::Config.new(&blk)
49
27
  end
50
28
  end
51
- extend ClassMethods
52
29
 
53
30
  end
54
31
 
@@ -64,10 +41,11 @@ require 'yaks/mapper/has_one'
64
41
  require 'yaks/mapper/has_many'
65
42
  require 'yaks/mapper/config'
66
43
  require 'yaks/mapper/class_methods'
67
- require 'yaks/mapper/map_links'
68
44
  require 'yaks/mapper'
69
45
  require 'yaks/collection_mapper'
70
46
 
71
47
  require 'yaks/serializer'
72
- require 'yaks/hal_serializer'
73
- require 'yaks/json_api_serializer'
48
+ require 'yaks/serializer/hal'
49
+ require 'yaks/serializer/json_api'
50
+ require 'yaks/serializer/collection_json'
51
+ require 'yaks/config'
data/notes.org ADDED
@@ -0,0 +1,72 @@
1
+ 0.4
2
+
3
+ * DONE Get rid of profile/rel registry, use policy instead
4
+ * DONE pass around policy explicitly instead of through options
5
+ * DONE introduce name/type separate from profile
6
+ ** DONE mapper
7
+ ** DONE Resource
8
+ * DONE allow setting rel types directly on associations, with fallback to policy
9
+ * DONE switch to hash-based init of Resource to make it more extensible
10
+ * DONE add Resource#type
11
+ * DONE not 100% happy yet about nameing of mapper#mapper_name / config#name. Maybe use `type` across the board?
12
+ * DONE Fix JsonAPISerializer
13
+ * top-level automatic links, e.g. for self and profile
14
+ * make HAL plural/singular links configurable from the Yaks.new
15
+ * make primitivize configuration instance based, not global
16
+ * Have JsonApi add self links as href: attributes
17
+ * Move examples to acceptance tests
18
+ * Select mapper based on content type
19
+ * move to 100% mutcov
20
+
21
+ pre 0.5
22
+
23
+ * CURIES/namespaces
24
+
25
+ Ticketsolve::Api::Yaks = ::Yaks.new do
26
+ policy do
27
+ def derive...
28
+ end
29
+
30
+ hal_options.plural_link '...'
31
+
32
+ primitivize Date, Time do |o|
33
+ o.iso8601
34
+ end
35
+
36
+ rel_template "http://literature.example.com/rel/#{association_name}"
37
+
38
+ link :self, "http://api.com/{key}/{id}"
39
+ link :profile, "http://api.com/profile/{key}"
40
+
41
+ # and/or
42
+ derive_rel_from_association do |mapper, association|
43
+ "http://literature.example.com/rel/#{association.name}"
44
+ end
45
+ end
46
+
47
+
48
+
49
+ * DONE 59 lib/yaks/mapper.rb
50
+ * DONE 92 lib/yaks/mapper/link.rb
51
+ * DONE 37 lib/yaks/mapper/association.rb
52
+ * DONE 3 lib/yaks/version.rb
53
+ * DONE 13 lib/yaks/mapper/has_many.rb
54
+ * DONE 9 lib/yaks/mapper/has_one.rb
55
+ * DONE 79 lib/yaks/config.rb
56
+ * 79 lib/yaks/mapper/config.rb
57
+ * 73 lib/yaks.rb
58
+ * DONE 72 lib/yaks/util.rb
59
+ * DONE 65 lib/yaks/collection_resource.rb
60
+ * 59 lib/yaks/json_api_serializer.rb
61
+ * 59 lib/yaks/hal_serializer.rb
62
+ * 43 lib/yaks/primitivize.rb
63
+ * 37 lib/yaks/mapper/class_methods.rb
64
+ * DONE 33 lib/yaks/collection_mapper.rb
65
+ * 28 lib/yaks/null_resource.rb
66
+ * DONE 27 lib/yaks/resource.rb
67
+ * 25 lib/yaks/resource/link.rb
68
+ * DONE 23 lib/yaks/fp.rb
69
+ * 22 lib/yaks/serializer.rb
70
+ * 15 lib/yaks/shared_options.rb
71
+ * 15 lib/yaks/default_policy.rb
72
+ * 10 lib/yaks/mapper/map_links.rb
data/shaved_yak.gif ADDED
Binary file
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+ require 'yaml'
3
+ require 'json'
4
+
5
+ require_relative './models'
6
+
7
+ RSpec.shared_examples_for 'JSON output format' do |yaks, format, name|
8
+ let(:input) { load_yaml_fixture name }
9
+ let(:output) { load_json_fixture "#{name}.#{format}" }
10
+
11
+ subject { yaks.serialize(input) }
12
+
13
+ it { should eql output }
14
+ end
15
+
16
+ RSpec.describe Yaks::Serializer::Hal do
17
+ yaks_rel_template = Yaks.new do
18
+ rel_template "http://literature.example.com/rel/{association_name}"
19
+ end
20
+
21
+ yaks_policy_dsl = Yaks.new do
22
+ derive_rel_from_association do |mapper, association|
23
+ "http://literature.example.com/rel/#{association.name}"
24
+ end
25
+ end
26
+
27
+ include_examples 'JSON output format' , yaks_rel_template , :hal , 'confucius'
28
+ include_examples 'JSON output format' , yaks_policy_dsl , :hal , 'confucius'
29
+ end
30
+
31
+ RSpec.describe Yaks::Serializer::JsonApi do
32
+ config = Yaks.new do
33
+ default_format :json_api
34
+ end
35
+
36
+ include_examples 'JSON output format' , config , :json_api , 'confucius'
37
+ end
38
+
39
+ RSpec.describe Yaks::Serializer::CollectionJson do
40
+ config = Yaks.new do
41
+ default_format :collection_json
42
+ mapper_namespace Youtypeitwepostit
43
+ end
44
+
45
+ include_examples 'JSON output format' , config , :collection , 'youtypeitwepostit'
46
+ end
@@ -0,0 +1,28 @@
1
+ require 'anima'
2
+
3
+ class Scholar
4
+ include Anima.new(:id, :name, :pinyin, :latinized, :works)
5
+ end
6
+
7
+ class Work
8
+ include Anima.new(:id, :chinese_name, :english_name)
9
+ end
10
+
11
+ class LiteratureBaseMapper < Yaks::Mapper
12
+ link :profile, 'http://literature.example.com/profiles/{mapper_name}'
13
+ link :self, 'http://literature.example.com/{mapper_name}/{id}'
14
+ end
15
+
16
+ class ScholarMapper < LiteratureBaseMapper
17
+ attributes :id, :name, :pinyin, :latinized
18
+ has_many :works
19
+ link :self, "http://literature.example.com/authors/{downcased_pinyin}"
20
+
21
+ def downcased_pinyin
22
+ object.pinyin.downcase
23
+ end
24
+ end
25
+
26
+ class WorkMapper < LiteratureBaseMapper
27
+ attributes :id, :chinese_name, :english_name
28
+ end
@@ -1,28 +1,24 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe 'Mapping domain models to Resource objects' do
3
+ RSpec.describe 'Mapping domain models to Resource objects' do
4
4
  include_context 'fixtures'
5
- include_context 'shorthands'
6
5
 
7
6
  subject { mapper.to_resource }
8
- let(:mapper) { FriendMapper.new(john) }
9
-
7
+ let(:mapper) { FriendMapper.new(john, policy: Yaks::DefaultPolicy.new, env: {}) }
10
8
 
11
9
  it { should be_a Yaks::Resource }
12
- its(:attributes) { should eq Yaks::Hash(id: 1, name: 'john') }
13
- its(:links) { should eq Yaks::List(
14
- resource_link[:profile, 'friend'],
15
- resource_link[:copyright, '/api/copyright/2024']
16
- )}
10
+ its(:type) { should eql 'friend' }
11
+ its(:attributes) { should eql(id: 1, name: 'john') }
12
+ its(:links) { should eql [ Yaks::Resource::Link.new(:copyright, '/api/copyright/2024', {}) ] }
17
13
 
18
14
  its(:subresources) {
19
- should eq Yaks::Hash(
20
- "rel:src=friend&dest=pet_peeve" => resource[{id: 4, type: 'parsing with regexps'}, [resource_link[:profile, 'pet_peeve']]],
15
+ should eq(
16
+ "rel:src=friend&dest=pet_peeve" => Yaks::Resource.new(type:'pet_peeve', attributes: {id: 4, type: 'parsing with regexps'}),
21
17
  "rel:src=friend&dest=pets" => Yaks::CollectionResource.new(
22
- [resource_link[:profile, 'pet']],
23
- [
24
- resource[{:id => 2, :species => "dog", :name => "boingboing"}, [resource_link[:profile, 'pet']]],
25
- resource[{:id => 3, :species => "cat", :name => "wassup"}, [resource_link[:profile, 'pet']]]
18
+ type: 'pet',
19
+ members: [
20
+ Yaks::Resource.new(type: 'pet', attributes: {:id => 2, :species => "dog", :name => "boingboing"}),
21
+ Yaks::Resource.new(type: 'pet', attributes: {:id => 3, :species => "cat", :name => "wassup"})
26
22
  ]
27
23
  )
28
24
  )
@@ -0,0 +1,23 @@
1
+ {
2
+ "id": 9,
3
+ "name": "孔子",
4
+ "pinyin": "Kongzi",
5
+ "latinized": "Confucius",
6
+ "_links": {
7
+ "self": { "href": "http://literature.example.com/authors/kongzi" },
8
+ "profile": { "href": "http://literature.example.com/profiles/scholar" }
9
+ },
10
+ "_embedded": {
11
+ "http://literature.example.com/rel/works": [
12
+ {
13
+ "id": 11,
14
+ "chinese_name": "論語",
15
+ "english_name": "Analects",
16
+ "_links": {
17
+ "self": { "href": "http://literature.example.com/work/11" },
18
+ "profile": { "href": "http://literature.example.com/profiles/work" }
19
+ }
20
+ }
21
+ ]
22
+ }
23
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "scholars": [
3
+ {
4
+ "id": 9,
5
+ "name": "孔子",
6
+ "pinyin": "Kongzi",
7
+ "latinized": "Confucius",
8
+ "links": {
9
+ "works": [11]
10
+ }
11
+ }
12
+ ],
13
+ "linked": {
14
+ "works": [
15
+ {
16
+ "id": 11,
17
+ "chinese_name": "論語",
18
+ "english_name": "Analects"
19
+ }
20
+ ]
21
+ }
22
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "id": 1,
3
+ "name": "john",
4
+ "_links": {
5
+ "copyright": [
6
+ {
7
+ "href": "/api/copyright/2024"
8
+ }
9
+ ]
10
+ },
11
+ "_embedded": {
12
+ "http://api.mysuperfriends.com/pet_peeve": {
13
+ "id": 4,
14
+ "type": "parsing with regexps"
15
+ },
16
+ "http://api.mysuperfriends.com/pets": [
17
+ {
18
+ "id": 2,
19
+ "name": "boingboing",
20
+ "species": "dog"
21
+ },
22
+ {
23
+ "id": 3,
24
+ "name": "wassup",
25
+ "species": "cat"
26
+ }
27
+ ]
28
+ }
29
+ }
@@ -0,0 +1,45 @@
1
+ {
2
+ "collection" :
3
+ {
4
+ "version" : "1.0",
5
+ "href" : "http://www.youtypeitwepostit.com/api/",
6
+
7
+ "items" :
8
+ [
9
+ {
10
+ "href": "http://www.youtypeitwepostit.com/api/12091295723803341",
11
+ "data": [
12
+ {
13
+ "name": "text",
14
+ "value": "massage"
15
+ },
16
+ {
17
+ "name": "date_posted",
18
+ "value": "2014-05-29T07:56:58.035Z"
19
+ }
20
+ ],
21
+ "links" :
22
+ [
23
+ { "rel": "profile", "href" : "http://www.youtypeitwepostit.com/profiles/message" }
24
+ ]
25
+ },
26
+ {
27
+ "href": "http://www.youtypeitwepostit.com/api/613856331910938",
28
+ "data": [
29
+ {
30
+ "name": "text",
31
+ "value": "Squid!"
32
+ },
33
+ {
34
+ "name": "date_posted",
35
+ "value": "2013-03-28T21:51:08.406Z"
36
+ }
37
+ ],
38
+ "links" :
39
+ [
40
+ { "rel": "profile", "href" : "http://www.youtypeitwepostit.com/profiles/message" }
41
+ ]
42
+ }
43
+ ]
44
+ }
45
+ }
data/spec/spec_helper.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'pathname'
2
+ require 'rspec/its'
2
3
 
3
4
  ROOT = Pathname(__FILE__).join('../..')
4
5
 
@@ -13,9 +14,19 @@ require_relative 'support/pet_mapper'
13
14
  require_relative 'support/pet_peeve_mapper'
14
15
  require_relative 'support/friends_mapper'
15
16
  require_relative 'support/fixtures'
16
- require_relative 'support/shorthands'
17
17
  require_relative 'support/shared_contexts'
18
+ require_relative 'support/youtypeit_models_mappers'
18
19
 
19
20
  def load_json_fixture(name)
20
21
  JSON.parse(ROOT.join('spec/json', name + '.json').read)
21
22
  end
23
+
24
+ def load_yaml_fixture(name)
25
+ YAML.load(ROOT.join('spec/yaml', name + '.yaml').read)
26
+ end
27
+
28
+ RSpec.configure do |rspec|
29
+ rspec.backtrace_exclusion_patterns = [] if ENV['FULLSTACK']
30
+ #rspec.disable_monkey_patching!
31
+ rspec.raise_errors_for_deprecations!
32
+ end
@@ -1,5 +1,5 @@
1
1
  shared_context 'collection resource' do
2
- let(:resource) { Yaks::CollectionResource.new(links, members) }
2
+ let(:resource) { Yaks::CollectionResource.new(links: links, members: members) }
3
3
  let(:links) { [] }
4
4
  let(:members) { [] }
5
5
  end
@@ -23,25 +23,22 @@ shared_context 'plant collection resource' do
23
23
 
24
24
  let(:plain_grass) do
25
25
  Yaks::Resource.new(
26
- {name: "Plain grass", type: "grass"},
27
- [plain_grass_self_link, plant_profile_link],
28
- {}
26
+ attributes: {name: "Plain grass", type: "grass"},
27
+ links: [plain_grass_self_link, plant_profile_link]
29
28
  )
30
29
  end
31
30
 
32
31
  let(:oak) do
33
32
  Yaks::Resource.new(
34
- {name: "Oak", type: "tree"},
35
- [oak_self_link, plant_profile_link],
36
- {}
33
+ attributes: {name: "Oak", type: "tree"},
34
+ links: [oak_self_link, plant_profile_link],
37
35
  )
38
36
  end
39
37
 
40
38
  let(:passiflora) do
41
39
  Yaks::Resource.new(
42
- {name: "Passiflora", type: "flower"},
43
- [passiflora_self_link, plant_profile_link],
44
- {}
40
+ attributes: {name: "Passiflora", type: "flower"},
41
+ links: [passiflora_self_link, plant_profile_link],
45
42
  )
46
43
  end
47
44
  end