roar-jsonapi 0.0.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.
@@ -0,0 +1,112 @@
1
+ Author = Struct.new(:id, :email, :name) do
2
+ def self.find_by(options)
3
+ AuthorNine if options[:id].to_s == '9'
4
+ end
5
+ end
6
+ AuthorNine = Author.new(9, '9@nine.to')
7
+
8
+ Article = Struct.new(:id, :title, :author, :editor, :comments) do
9
+ def reviewers
10
+ ['Christian Bernstein']
11
+ end
12
+ end
13
+
14
+ Comment = Struct.new(:comment_id, :body) do
15
+ def self.find_by(_options)
16
+ new
17
+ end
18
+ end
19
+
20
+ class AuthorDecorator < Roar::Decorator
21
+ include Roar::JSON::JSONAPI.resource :authors
22
+
23
+ attributes do
24
+ property :email
25
+ end
26
+
27
+ link(:self) { "http://authors/#{represented.id}" }
28
+ end
29
+
30
+ class CommentDecorator < Roar::Decorator
31
+ include Roar::JSON::JSONAPI.resource(:comments, id_key: :comment_id)
32
+
33
+ attributes do
34
+ property :body
35
+ end
36
+
37
+ link(:self) { "http://comments/#{represented.comment_id}" }
38
+ end
39
+
40
+ class ArticleDecorator < Roar::Decorator
41
+ include Roar::JSON::JSONAPI.resource :articles
42
+
43
+ # top-level link.
44
+ link :self, toplevel: true do |options|
45
+ if options
46
+ "//articles?page=#{options[:page]}&per_page=#{options[:per_page]}"
47
+ else
48
+ '//articles'
49
+ end
50
+ end
51
+
52
+ meta toplevel: true do
53
+ property :count
54
+ end
55
+
56
+ attributes do
57
+ property :title
58
+ end
59
+
60
+ meta do
61
+ collection :reviewers
62
+ end
63
+
64
+ meta do
65
+ property :reviewer_initials, getter: ->(_) {
66
+ reviewers.map { |reviewer|
67
+ reviewer.split.map { |name| "#{name[0]}." }.join
68
+ }.join(', ')
69
+ }
70
+ end
71
+
72
+ # resource object links
73
+ link(:self) { "http://#{represented.class}/#{represented.id}" }
74
+
75
+ # relationships
76
+ has_one :author, class: Author, decorator: AuthorDecorator,
77
+ populator: ::Representable::FindOrInstantiate do # populator is for parsing, only.
78
+
79
+ relationship do
80
+ link(:self) { "/articles/#{represented.id}/relationships/author" }
81
+ link(:related) { "/articles/#{represented.id}/author" }
82
+ end
83
+ end
84
+
85
+ has_one :editor do
86
+ type :editors
87
+
88
+ relationship do
89
+ meta do
90
+ property :peer_reviewed, getter: ->(_) { false }
91
+ end
92
+ end
93
+
94
+ attributes do
95
+ property :email
96
+ end
97
+ # No self link for editors because we want to make sure the :links option does not appear in the hash.
98
+ end
99
+
100
+ has_many :comments, class: Comment, decorator: CommentDecorator,
101
+ populator: ::Representable::FindOrInstantiate do
102
+
103
+ relationship do
104
+ link(:self) { "/articles/#{represented.id}/relationships/comments" }
105
+ link(:related) { "/articles/#{represented.id}/comments" }
106
+
107
+ meta do
108
+ property :count, as: 'comment-count'
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,88 @@
1
+ # encoding: utf-8
2
+
3
+ require 'test_helper'
4
+ require 'roar/json/json_api'
5
+ require 'json'
6
+
7
+ class ResourceLinkageTest < MiniTest::Spec
8
+ class ChefDecorator < Roar::Decorator
9
+ include Roar::JSON::JSONAPI.resource :chefs
10
+
11
+ attributes do
12
+ property :name
13
+ end
14
+ end
15
+
16
+ class IngredientDecorator < Roar::Decorator
17
+ include Roar::JSON::JSONAPI.resource :ingredients
18
+
19
+ attributes do
20
+ property :name
21
+ end
22
+ end
23
+
24
+ class RecipeDecorator < Roar::Decorator
25
+ include Roar::JSON::JSONAPI.resource :recipes
26
+
27
+ attributes do
28
+ property :name
29
+ end
30
+
31
+ has_one :chef, decorator: ChefDecorator
32
+ has_many :ingredients, decorator: IngredientDecorator
33
+
34
+ has_many :reviews do
35
+ type :review
36
+
37
+ attributes do
38
+ property :text
39
+ end
40
+ end
41
+ end
42
+
43
+ Recipe = Struct.new(:id, :name, :chef, :ingredients, :reviews)
44
+ Chef = Struct.new(:id, :name)
45
+ Ingredient = Struct.new(:id, :name)
46
+
47
+ let(:doc) { RecipeDecorator.new(souffle).to_hash }
48
+ let(:doc_relationships) { doc['data']['relationships'] }
49
+
50
+ describe 'non-empty relationships' do
51
+ let(:souffle) {
52
+ Recipe.new(1, 'Cheese soufflé',
53
+ Chef.new(1, 'Jamie Oliver'),
54
+ [Ingredient.new(5, 'Eggs'), Ingredient.new(6, 'Gruyère')])
55
+ }
56
+
57
+ it 'renders a single object for non-empty to-one relationships' do
58
+ doc_relationships['chef'].must_equal('data'=>{ 'type' => 'chefs', 'id' => '1' })
59
+ end
60
+
61
+ it 'renders an array for non-empty to-many relationships' do
62
+ doc_relationships['ingredients'].must_equal('data' => [
63
+ { 'type' => 'ingredients', 'id' => '5' },
64
+ { 'type' => 'ingredients', 'id' => '6' }
65
+ ])
66
+ end
67
+ end
68
+
69
+ describe 'empty (nil) relationships' do
70
+ let(:souffle) { Recipe.new(1, 'Cheese soufflé', nil, nil) }
71
+
72
+ it 'renders null for an empty to-one relationships' do
73
+ doc_relationships['chef'].must_equal('data' => nil)
74
+ end
75
+
76
+ it 'renders an empty array ([]) for empty (nil) to-many relationships' do
77
+ doc_relationships['ingredients'].must_equal('data' => [])
78
+ end
79
+ end
80
+
81
+ describe 'empty to-many relationships' do
82
+ let(:souffle) { Recipe.new(1, 'Cheese soufflé', nil, []) }
83
+
84
+ it 'renders an empty array ([]) for empty to-many relationships' do
85
+ doc_relationships['ingredients'].must_equal('data' => [])
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,42 @@
1
+ require 'minitest/autorun'
2
+ require 'minitest/reporters'
3
+ Minitest::Reporters.use! Minitest::Reporters::DefaultReporter.new
4
+
5
+ require 'roar/representer'
6
+ require 'roar/json'
7
+ require 'roar/json/json_api'
8
+
9
+ require 'representable/debug'
10
+ require 'pp'
11
+
12
+ require_relative 'jsonapi/representer'
13
+
14
+ require 'json_spec/configuration'
15
+ require 'json_spec/helpers'
16
+ require 'json_spec/exclusion'
17
+
18
+ if system('colordiff', __FILE__, __FILE__)
19
+ MiniTest::Assertions.diff = 'colordiff -u'
20
+ end
21
+
22
+ module JsonSpec
23
+ extend Configuration
24
+
25
+ self.excluded_keys = []
26
+ end
27
+ module MiniTest::Assertions
28
+ def assert_equal_json(actual, expected)
29
+ assert_equal scrub(actual), scrub(expected)
30
+ end
31
+
32
+ def scrub(json, path = nil)
33
+ JsonSpec::Helpers.generate_normalized_json(
34
+ JsonSpec::Exclusion.exclude_keys(
35
+ JsonSpec::Helpers.parse_json(json, path)
36
+ )
37
+ ).chomp + "\n"
38
+ end
39
+ end
40
+ module Minitest::Expectations
41
+ infect_an_assertion :assert_equal_json, :must_equal_json
42
+ end
metadata ADDED
@@ -0,0 +1,132 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: roar-jsonapi
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Nick Sutterer
8
+ - Alex Coles
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2017-01-12 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: roar
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '1.1'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '1.1'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rake
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: 0.10.1
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: 0.10.1
42
+ - !ruby/object:Gem::Dependency
43
+ name: minitest
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '5.10'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '5.10'
56
+ - !ruby/object:Gem::Dependency
57
+ name: multi_json
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ description: Object-oriented representers help you define nested JSON API documents
71
+ which can then be rendered and parsed using one and the same concept.
72
+ email:
73
+ - apotonick@gmail.com
74
+ - alex@alexbcoles.com
75
+ executables: []
76
+ extensions: []
77
+ extra_rdoc_files: []
78
+ files:
79
+ - ".gitignore"
80
+ - ".rubocop.yml"
81
+ - ".travis.yml"
82
+ - ".yardopts"
83
+ - CONTRIBUTING.md
84
+ - Gemfile
85
+ - ISSUE_TEMPLATE.md
86
+ - LICENSE
87
+ - README.markdown
88
+ - Rakefile
89
+ - lib/roar/json/json_api.rb
90
+ - lib/roar/json/json_api/declarative.rb
91
+ - lib/roar/json/json_api/defaults.rb
92
+ - lib/roar/json/json_api/document.rb
93
+ - lib/roar/json/json_api/for_collection.rb
94
+ - lib/roar/json/json_api/member_name.rb
95
+ - lib/roar/json/json_api/meta.rb
96
+ - lib/roar/json/json_api/options.rb
97
+ - lib/roar/json/json_api/version.rb
98
+ - roar-jsonapi.gemspec
99
+ - test/jsonapi/collection_render_test.rb
100
+ - test/jsonapi/fieldsets_options_test.rb
101
+ - test/jsonapi/fieldsets_test.rb
102
+ - test/jsonapi/member_name_test.rb
103
+ - test/jsonapi/post_test.rb
104
+ - test/jsonapi/render_test.rb
105
+ - test/jsonapi/representer.rb
106
+ - test/jsonapi/resource_linkage_test.rb
107
+ - test/test_helper.rb
108
+ homepage: http://trailblazer.to/gems/roar/jsonapi.html
109
+ licenses:
110
+ - MIT
111
+ metadata: {}
112
+ post_install_message:
113
+ rdoc_options: []
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ requirements: []
127
+ rubyforge_project:
128
+ rubygems_version: 2.5.1
129
+ signing_key:
130
+ specification_version: 4
131
+ summary: Parse and render JSON API documents using representers.
132
+ test_files: []