jacoat 0.1.0 → 0.1.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b90bcea2b15f17d4e2766df1d3a8c18c50de275f
4
- data.tar.gz: 4e11452c19ca00e9f38edbb110f6cb52d8f74073
3
+ metadata.gz: 396c87751d11cb60f85a7c3c671fe33043989aed
4
+ data.tar.gz: abae97ede6d6d52177f26a381ecac86f8877fdac
5
5
  SHA512:
6
- metadata.gz: c0b4091682a4daaedf3c1eabf199e1a731ff78728283a26db4acdba7904f21955139f84602e7ace4af2d6d6b9da4b37cfc410be7b5f4d081a7263915cc44ed8f
7
- data.tar.gz: 9fb97a37ba63348520f9157702f94b4e0fe6c214f3e41e5fd1adbaeb7b5119d203c92f9b857dc672b6914352e2fec96ca7083b8f32fa5e87171d61474efe75b5
6
+ metadata.gz: 25bedd6912572567f7ac48970f8fc4c47f11418a7fb533dd6aea6eb7cf783ea8bc19c58e985d9711fe84797ef04a08d3b587054d12f3923841d2624363790370
7
+ data.tar.gz: d4158ab50b8ff54d2c227d35e6d2ad87b3b12e3a0aa7ac8c65b0e368b9c4f740f505d9a4e361a7c505bf442abe0a64f8435d33d77e01b5b477d0910266ef52e3
data/jacoat.gemspec CHANGED
@@ -21,5 +21,7 @@ Gem::Specification.new do |spec|
21
21
 
22
22
  spec.add_development_dependency "bundler", "~> 1.10"
23
23
  spec.add_development_dependency "rake", "~> 10.0"
24
+ spec.add_development_dependency "representable", "~> 2.3"
25
+ spec.add_development_dependency "multi_json", "~> 1.11"
24
26
  spec.add_development_dependency "rspec"
25
27
  end
@@ -11,22 +11,38 @@ require 'jacoat/document/relationship'
11
11
 
12
12
  module Jacoat
13
13
  class Document
14
- attr_reader :data, :errors, :meta, :jsonapi, :links, :included
15
- def initialize(arguments = {})
16
- validate_arguments(arguments)
17
- @has_data = true if arguments.has_key?(:data)
18
- @data = Data.process(arguments[:data]) if arguments.has_key?(:data)
19
- @errors = Error.new(arguments[:errors]) if arguments.has_key?(:errors)
20
- @meta = Meta.new(arguments[:meta]) if arguments.has_key?(:meta)
21
- @jsonapi = Jsonapi.new(arguments[:jsonapi]) if arguments.has_key?(:jsonapi)
22
- @links = Link.process(arguments[:links]) if arguments.has_key?(:links)
23
- @included = Included.process(arguments[:included]) if arguments.has_key?(:included)
14
+ attr_reader :data
15
+ attr_accessor :errors, :meta, :jsonapi, :links, :included
16
+
17
+ def self.from_jsonapi(arguments)
18
+ document = Document.new
19
+ document.data = Data.from_jsonapi(arguments[:data]) if arguments.has_key?(:data)
20
+
21
+
22
+ document.errors = Error.from_jsonapi(arguments[:errors]) if arguments.has_key?(:errors)
23
+ document.meta = Meta.from_jsonapi(arguments[:meta]) if arguments.has_key?(:meta)
24
+ document.jsonapi = Jsonapi.from_jsonapi(arguments[:jsonapi]) if arguments.has_key?(:jsonapi)
25
+ document.links = Link.from_jsonapi(arguments[:links]) if arguments.has_key?(:links)
26
+ document.included = Included.from_jsonapi(arguments[:included]) if arguments.has_key?(:included)
27
+ document
24
28
  end
25
-
26
- def validate_arguments(arguments)
27
- raise Invalid.new('included key without data key') if arguments.has_key?(:included) && !arguments.has_key?(:data)
28
- raise Invalid.new('must contain data, errors or meta key') if !arguments.has_key?(:data) && !arguments.has_key?(:errors) && !arguments.has_key?(:meta)
29
- raise Invalid.new('data and errors keys set') if arguments.has_key?(:data) && arguments.has_key?(:errors)
29
+
30
+ def data=(data)
31
+ @has_data = true
32
+ @data = data
33
+ end
34
+
35
+ def valid?
36
+ validate_arguments
37
+ true
38
+ rescue Invalid
39
+ return false
40
+ end
41
+
42
+ def validate_arguments
43
+ raise Invalid.new('included key without data key') if @included && !@data
44
+ raise Invalid.new('must contain data, errors or meta key') if !@data && !@errors && !@meta
45
+ raise Invalid.new('data and errors keys set') if @data && @errors
30
46
  end
31
47
 
32
48
  def to_hash
@@ -1,6 +1,12 @@
1
1
  module Jacoat
2
2
  class Document
3
3
  class Attributes
4
+ attr_reader :hash
5
+
6
+ def self.from_jsonapi(arguments = {})
7
+ Attributes.new(arguments)
8
+ end
9
+
4
10
  def initialize(arguments = {})
5
11
  @hash = arguments
6
12
  end
@@ -1,7 +1,7 @@
1
1
  module Jacoat
2
2
  class Document
3
3
  class Data
4
- def self.process(arguments)
4
+ def self.from_jsonapi(arguments)
5
5
  data = Data.new
6
6
  if arguments.is_a?(Array)
7
7
  data.resource = create_resource_array(arguments)
@@ -14,9 +14,9 @@ module Jacoat
14
14
  def self.create_resource(arguments)
15
15
  return nil if arguments.nil?
16
16
  if Detector.what_is(arguments) == "resource"
17
- return Resource.new(arguments)
17
+ return Resource.from_jsonapi(arguments)
18
18
  else
19
- return ResourceIdentifier.new(arguments)
19
+ return ResourceIdentifier.from_jsonapi(arguments)
20
20
  end
21
21
  end
22
22
 
@@ -24,15 +24,18 @@ module Jacoat
24
24
  resources = []
25
25
  arguments.each do |resource|
26
26
  if Detector.what_is(resource) == "resource"
27
- resources << Resource.new(resource)
27
+ resources << Resource.from_jsonapi(resource)
28
28
  else
29
- resources << ResourceIdentifier.new(resource)
29
+ resources << ResourceIdentifier.from_jsonapi(resource)
30
30
  end
31
31
  end
32
32
  resources
33
33
  end
34
34
 
35
- attr_accessor :resource
35
+ attr_accessor :resource
36
+ def resources=(resources)
37
+ @resource = resources
38
+ end
36
39
  def resources
37
40
  @resource
38
41
  end
@@ -1,14 +1,16 @@
1
1
  module Jacoat
2
2
  class Document
3
3
  class Error
4
- attr_reader :id, :links, :status, :code, :title, :detail, :meta
5
- def initialize(arguments = {})
6
- @id = arguments[:id]
7
- @links = Link.process(arguments[:links]) if arguments.has_key?(:links)
4
+ attr_accessor :id, :links, :status, :code, :title, :detail, :meta
5
+ def self.from_jsonapi(arguments)
6
+ error = Error.new
7
+ error.id = arguments[:id]
8
+ error.links = Link.from_jsonapi(arguments[:links]) if arguments.has_key?(:links)
8
9
  %w{ status code title detail }.each do |type|
9
- self.instance_variable_set("@#{type}", arguments[type.to_sym]) if arguments.has_key?(type.to_sym)
10
+ error.instance_variable_set("@#{type}", arguments[type.to_sym]) if arguments.has_key?(type.to_sym)
10
11
  end
11
- @meta = Meta.new(arguments[:meta]) if arguments.has_key?(:meta)
12
+ error.meta = Meta.from_jsonapi(arguments[:meta]) if arguments.has_key?(:meta)
13
+ error
12
14
  end
13
15
 
14
16
  def to_hash
@@ -1,10 +1,10 @@
1
1
  module Jacoat
2
2
  class Document
3
3
  class Included
4
- def self.process(arguments)
4
+ def self.from_jsonapi(arguments)
5
5
  resources = []
6
6
  arguments.each do |item|
7
- resources << Resource.new(item)
7
+ resources << Resource.from_jsonapi(item)
8
8
  end
9
9
  included = Included.new
10
10
  included.resources = resources
@@ -1,9 +1,12 @@
1
1
  module Jacoat
2
2
  class Document
3
3
  class Jsonapi
4
- attr_reader :version
5
- def initialize(arguments = {})
6
- @version = arguments[:version]
4
+ attr_accessor :version
5
+
6
+ def self.from_jsonapi(arguments)
7
+ jsonapi = Jsonapi.new
8
+ jsonapi.version = arguments[:version]
9
+ jsonapi
7
10
  end
8
11
 
9
12
  def to_hash
@@ -1,13 +1,14 @@
1
1
  module Jacoat
2
2
  class Document
3
3
  class Link
4
- def self.process(hash)
5
- Link.new(hash)
4
+ def self.from_jsonapi(hash)
5
+ link = Link.new
6
+ link.process_links(hash)
7
+ link
6
8
  end
7
9
 
8
- def initialize(arguments = {})
10
+ def initialize
9
11
  @hash = {}
10
- process_links(arguments)
11
12
  end
12
13
 
13
14
  def method_missing(m, *args)
@@ -26,18 +27,28 @@ module Jacoat
26
27
  end
27
28
  hash
28
29
  end
29
-
30
- private
31
- def process_links(arguments)
32
- arguments.each_pair do |k, v|
33
- if v.is_a?(String)
34
- link = Simple.new(v)
35
- else
36
- link = Complex.new(v)
37
- end
38
- send("#{k}=", link)
30
+
31
+ def process_links(arguments)
32
+ return if arguments.nil?
33
+ arguments.each_pair do |k, v|
34
+ if v.is_a?(String)
35
+ link = Simple.new(v)
36
+ else
37
+ link = Complex.new(v)
39
38
  end
39
+ send("#{k}=", link)
40
40
  end
41
+ end
42
+
43
+ def add_link(title, href, options = {})
44
+ if options.empty?
45
+ link = Simple.new(href)
46
+ else
47
+ link = Complex.new(href: href, meta: options)
48
+ end
49
+ send("#{title}=", link)
50
+ self
51
+ end
41
52
 
42
53
  class Simple
43
54
  attr_reader :href
@@ -54,7 +65,7 @@ module Jacoat
54
65
  attr_reader :href, :meta
55
66
  def initialize(arguments)
56
67
  @href = arguments[:href]
57
- @meta = Meta.new(arguments[:meta])
68
+ @meta = Meta.from_jsonapi(arguments[:meta])
58
69
  end
59
70
 
60
71
  def to_hash
@@ -1,9 +1,14 @@
1
1
  module Jacoat
2
2
  class Document
3
3
  class Meta
4
+ def self.from_jsonapi(arguments)
5
+ meta = Meta.new
6
+ meta.process_meta(arguments)
7
+ meta
8
+ end
9
+
4
10
  def initialize(arguments = {})
5
11
  @hash = {}
6
- process_meta(arguments)
7
12
  end
8
13
 
9
14
  def method_missing(m, *args)
@@ -19,12 +24,11 @@ module Jacoat
19
24
  @hash
20
25
  end
21
26
 
22
- private
23
- def process_meta(arguments)
24
- arguments.each_pair do |k, v|
25
- send("#{k}=", v)
26
- end
27
+ def process_meta(arguments)
28
+ arguments.each_pair do |k, v|
29
+ send("#{k}=", v)
27
30
  end
31
+ end
28
32
  end
29
33
  end
30
34
  end
@@ -1,19 +1,19 @@
1
1
  module Jacoat
2
2
  class Document
3
3
  class Relationship
4
- attr_reader :id, :type, :data, :links
5
- def self.process(hash)
4
+ attr_accessor :id, :type, :data, :links
5
+ def self.from_jsonapi(hash)
6
6
  relationships = []
7
7
  hash.each_pair do |k, v|
8
- relationships << Document::Relationship.new(k, v)
8
+ relationship = Document::Relationship.new(k)
9
+ relationship.process_jsonapi(v)
10
+ relationships << relationship
9
11
  end
10
12
  relationships
11
13
  end
12
14
 
13
- def initialize(type, body)
15
+ def initialize(type)
14
16
  @type = type.to_s
15
- process_data(body[:data]) if body.has_key?(:data)
16
- process_body(body[:links]) if body.has_key?(:links)
17
17
  end
18
18
 
19
19
  def to_hash
@@ -24,13 +24,19 @@ module Jacoat
24
24
  hash
25
25
  end
26
26
 
27
+ def process_jsonapi(hash)
28
+ process_data(hash[:data]) if hash.has_key?(:data)
29
+ process_body(hash[:links]) if hash.has_key?(:links)
30
+ self
31
+ end
32
+
27
33
  private
28
34
  def process_data(data)
29
- @data = Document::ResourceIdentifier.process(data)
35
+ @data = Document::ResourceIdentifier.from_jsonapi(data)
30
36
  end
31
37
 
32
38
  def process_body(links)
33
- @links = Document::Link.process(links)
39
+ @links = Document::Link.from_jsonapi(links)
34
40
  end
35
41
 
36
42
  def data_to_hash
@@ -1,19 +1,25 @@
1
1
  module Jacoat
2
2
  class Document
3
3
  class Resource
4
- attr_reader :id, :type, :attributes, :links, :relationships
5
- def initialize(arguments)
6
- @id = arguments[:id]
7
- @type = arguments[:type]
8
- @attributes = Document::Attributes.new(arguments[:attributes])
9
- create_relationships(arguments[:relationships]) if arguments.has_key?(:relationships)
10
- @links = Link.process(arguments[:links]) if arguments.has_key?(:links)
4
+ attr_accessor :id, :type, :attributes, :links, :relationships
5
+
6
+ def self.from_jsonapi(arguments)
7
+ resource = Resource.new(arguments[:id], arguments[:type])
8
+ resource.attributes = Document::Attributes.from_jsonapi(arguments[:attributes])
9
+ resource.create_relationships(arguments[:relationships]) if arguments.has_key?(:relationships)
10
+ resource.links = Link.from_jsonapi(arguments[:links]) if arguments.has_key?(:links)
11
+ resource
12
+ end
13
+
14
+ def initialize(id, type)
15
+ @id = id
16
+ @type = type
11
17
  end
12
18
 
13
19
  def create_relationships(hash)
14
20
  @relationships = []
15
21
  hash.each_pair do |k, v|
16
- @relationships << Document::Relationship.new(k, v)
22
+ @relationships << Document::Relationship.new(k).process_jsonapi(v)
17
23
  end
18
24
  end
19
25
 
@@ -1,29 +1,33 @@
1
1
  module Jacoat
2
2
  class Document
3
3
  class ResourceIdentifier
4
- attr_reader :id, :type, :relationships
5
- def self.process(body)
4
+ attr_accessor :id, :type, :relationships
5
+ def self.from_jsonapi(body)
6
6
  if body.is_a?(Array)
7
7
  resources = []
8
8
  body.each do |item|
9
- resources << ResourceIdentifier.new(item)
9
+ resources << ResourceIdentifier.new(item[:id], item[:type]).process_jsonapi(item)
10
10
  end
11
11
  else
12
- resources = ResourceIdentifier.new(body)
12
+ resources = ResourceIdentifier.new(body[:id], body[:type]).process_jsonapi(body)
13
13
  end
14
14
  resources
15
15
  end
16
16
 
17
- def initialize(arguments)
18
- @id = arguments[:id]
19
- @type = arguments[:type]
17
+ def initialize(id, type)
18
+ @id = id
19
+ @type = type
20
+ end
21
+
22
+ def process_jsonapi(arguments)
20
23
  create_relationships(arguments[:relationships]) if arguments.has_key?(:relationships)
24
+ self
21
25
  end
22
26
 
23
27
  def create_relationships(hash)
24
28
  @relationships = []
25
29
  hash.each_pair do |k, v|
26
- @relationships << Document::Relationship.new(k, v)
30
+ @relationships << Document::Relationship.new(k).process_jsonapi(v)
27
31
  end
28
32
  end
29
33
 
@@ -0,0 +1,147 @@
1
+ require 'multi_json'
2
+ require 'representable/json'
3
+ require 'representable/hash_methods'
4
+ require 'jacoat/representable/has_one'
5
+
6
+ module Jacoat
7
+ module Representable
8
+ attr_accessor :type
9
+
10
+ def self.included(base)
11
+ base.class_eval do
12
+ include ::Representable
13
+ include ::Representable::JSON
14
+ extend ClassMethods
15
+ include InstanceMethods
16
+ end
17
+ end
18
+
19
+ module ClassMethods
20
+ def type(type)
21
+ representable_attrs[:_type] = type.to_s
22
+ end
23
+
24
+ def links
25
+ end
26
+
27
+ def link(link, &block)
28
+ representable_attrs[:_link] = {} if representable_attrs[:_link].nil?
29
+ representable_attrs[:_link][link] = block if block_given?
30
+ end
31
+
32
+ def has_one(name, options = {}, &block)
33
+ add_relationship(name, :_has_one, options, block)
34
+ end
35
+
36
+ def has_many(name, options = {}, &block)
37
+ add_relationship(name, :_has_many, options, block)
38
+ end
39
+
40
+ def relationships
41
+ end
42
+
43
+ private
44
+ def add_relationship(object, type, options, block)
45
+ representable_attrs[type] = {} unless representable_attrs.has_key?(type)
46
+ rel = HasOne.new
47
+ rel.options = options
48
+ rel.instance_eval(&block)
49
+ representable_attrs[type][object] = rel
50
+ end
51
+ end
52
+
53
+ module InstanceMethods
54
+ def from_hash(hash, options={})
55
+ hash = from_document(hash)
56
+ super(hash, options.merge(:only_body => true))
57
+ end
58
+
59
+ def to_hash(options={})
60
+ res = super(options.merge(:only_body => true))
61
+ to_document(res, options)
62
+ end
63
+
64
+ private
65
+ def from_document(hash)
66
+ document = Jacoat::Document.from_jsonapi(symbolize_keys(hash))
67
+ attributes = document.data.resource.attributes.hash
68
+ attributes = from_document_set_relationships(hash, attributes)
69
+ stringify_keys(attributes)
70
+ end
71
+
72
+ def from_document_set_relationships(hash, attributes)
73
+ representable_attrs[:_has_one].each_key do |k|
74
+ attributes["#{k}_id"] = hash["data"]["relationships"][k.to_s]["data"]["id"].to_i
75
+ end
76
+ attributes
77
+ end
78
+
79
+ def to_document(hash, options = {})
80
+ document = Jacoat::Document.new
81
+ document.data = generate_resource(hash)
82
+ document.data.relationships = relationship_array(hash)
83
+ document.links = generate_links(hash)
84
+ document.to_hash
85
+ end
86
+
87
+ def generate_links(hash)
88
+ lk = Jacoat::Document::Link.new
89
+ @representable_attrs[:_link].each_pair do |link, block|
90
+ href = represented.instance_eval(&@representable_attrs[:_link][link.to_sym])
91
+ lk.add_link(link.to_s, href)
92
+ end
93
+ lk
94
+ end
95
+
96
+ def generate_resource(hash)
97
+ id = hash.delete("id")
98
+ res = Jacoat::Document::Resource.new(id, representable_attrs[:_type])
99
+ res.attributes = Jacoat::Document::Attributes.new(hash)
100
+ res
101
+ end
102
+
103
+ def relationship_array(hash)
104
+ relationships = []
105
+ @representable_attrs[:_has_one].each_pair do |item, object|
106
+ rel = Jacoat::Document::Relationship.new(item.to_s)
107
+ object.links.each_pair do |k, block|
108
+ href = represented.instance_eval(&block)
109
+ rel.links = Jacoat::Document::Link.new.add_link(k.to_s, href)
110
+ end
111
+ relationships.push(rel)
112
+ end
113
+ relationships
114
+ end
115
+
116
+ def symbolize_keys(hash)
117
+ hash.inject({}){|result, (key, value)|
118
+ new_key = case key
119
+ when String then key.to_sym
120
+ else key
121
+ end
122
+ new_value = case value
123
+ when Hash then symbolize_keys(value)
124
+ else value
125
+ end
126
+ result[new_key] = new_value
127
+ result
128
+ }
129
+ end
130
+
131
+ def stringify_keys(hash)
132
+ hash.inject({}){|result, (key, value)|
133
+ new_key = case key
134
+ when Symbol then key.to_s
135
+ else key
136
+ end
137
+ new_value = case value
138
+ when Hash then symbolize_keys(value)
139
+ else value
140
+ end
141
+ result[new_key] = new_value
142
+ result
143
+ }
144
+ end
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,12 @@
1
+ module Jacoat
2
+ module Representable
3
+ class HasOne
4
+ attr_accessor :links, :options
5
+
6
+ def link(link, &block)
7
+ @links = {} if @links.nil?
8
+ @links[link] = block
9
+ end
10
+ end
11
+ end
12
+ end
@@ -1,3 +1,3 @@
1
1
  module Jacoat
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jacoat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Celso Fernandes
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-10-14 00:00:00.000000000 Z
11
+ date: 2015-10-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -38,6 +38,34 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: representable
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: multi_json
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.11'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.11'
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: rspec
43
71
  requirement: !ruby/object:Gem::Requirement
@@ -83,6 +111,8 @@ files:
83
111
  - lib/jacoat/document/relationship.rb
84
112
  - lib/jacoat/document/resource.rb
85
113
  - lib/jacoat/document/resource_identifier.rb
114
+ - lib/jacoat/representable.rb
115
+ - lib/jacoat/representable/has_one.rb
86
116
  - lib/jacoat/version.rb
87
117
  homepage: http://github.com/fernandes/jacoat
88
118
  licenses:
@@ -104,7 +134,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
104
134
  version: '0'
105
135
  requirements: []
106
136
  rubyforge_project:
107
- rubygems_version: 2.4.8
137
+ rubygems_version: 2.4.5.1
108
138
  signing_key:
109
139
  specification_version: 4
110
140
  summary: Your JSON-API Coat in Ruby