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,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ece64905f608afe23b1ff500b22cc2735773ff4d
4
+ data.tar.gz: 8b9b74e066c310d7dfcc1fb615ec050df9e825ea
5
+ SHA512:
6
+ metadata.gz: f9617c6cbe337a9d0533f67426fd6b8ce83420e7873f783acea631e7227a39e59097dd11b4a80916d694b2d5771dd9a47da2e7212c12096960eaf72e7058ce3b
7
+ data.tar.gz: 320c347be830d71313d237cb66460dfa1ef63ae0492c73d6064f3e5cba0bf50497a1c51769c249ae9a7047681063d659d81e1b0f97aa2fe9e0f2ed797fd86d20
@@ -0,0 +1,5 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
4
+ Gemfile*.lock
5
+ .idea
@@ -0,0 +1,37 @@
1
+ AllCops:
2
+ TargetRubyVersion: 1.9
3
+
4
+ Style/AlignHash:
5
+ EnforcedHashRocketStyle: table
6
+ EnforcedColonStyle: table
7
+
8
+ Style/AndOr:
9
+ EnforcedStyle: conditionals
10
+
11
+ Style/BlockDelimiters:
12
+ Enabled: true
13
+ EnforcedStyle: semantic
14
+ IgnoredMethods:
15
+ - lambda
16
+ - proc
17
+ - it
18
+ - link
19
+
20
+ Style/Lambda:
21
+ Enabled: false
22
+ EnforcedStyle: literal
23
+
24
+ Style/LambdaCall:
25
+ EnforcedStyle: braces
26
+
27
+ Metrics/LineLength:
28
+ Enabled: false
29
+
30
+ Metrics/MethodLength:
31
+ Max: 15
32
+
33
+ Style/PredicateName:
34
+ NameWhitelist:
35
+ - is_a?
36
+ - has_one
37
+ - has_many
@@ -0,0 +1,14 @@
1
+ sudo: false
2
+ language: ruby
3
+ cache: bundler
4
+ rvm:
5
+ - 1.9.3
6
+ - 2.1
7
+ - 2.2.6
8
+ - 2.3.1
9
+ - 2.4.0
10
+ - jruby-9.1.6.0
11
+ - ruby-head
12
+ matrix:
13
+ allow_failures:
14
+ - rvm: ruby-head
@@ -0,0 +1,5 @@
1
+ --markup markdown
2
+ --no-private
3
+ -
4
+ README.markdown
5
+ LICENSE
@@ -0,0 +1,31 @@
1
+ ## How to contribute to Roar
2
+
3
+ #### **Did you find a bug?**
4
+
5
+ * **Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/trailblazer/roar-jsonapi/issues).
6
+
7
+ * If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/trailblazer/roar-jsonapi/issues/new). Be sure to follow the issue template.
8
+
9
+ #### **Did you write a patch that fixes a bug?**
10
+
11
+ * Open a new GitHub pull request with the patch.
12
+
13
+ * Ensure the PR description clearly describes the problem and solution. Include the relevant issue number if applicable.
14
+
15
+ * All code in pull requests is assumed to be MIT licensed. Do not submit a pull request if that isn't the case.
16
+
17
+ #### **Do you intend to add a new feature or change an existing one?**
18
+
19
+ * Suggest your change in the [Trailblazer Gitter Room](https://gitter.im/trailblazer/chat) and start writing code.
20
+
21
+ * Do not open an issue on GitHub until you have collected positive feedback about the change. GitHub issues are primarily intended for bug reports and fixes.
22
+
23
+ #### **Do you have questions using Roar?**
24
+
25
+ * Ask any questions about how to use Roar in the [Trailblazer Gitter Room](https://gitter.im/trailblazer/chat). Github issues are restricted to bug reports and fixes.
26
+
27
+ * GitHub Issues should not be used as a help forum and any such issues will be closed.
28
+
29
+ #### **Do you want to contribute to the Roar documentation?**
30
+
31
+ * Roar documentation is provided via the [Trailblazer site](http://trailblazer.to/gems/roar/) and not the repository readme. Please add your contributions to the [Trailblazer site repository](https://github.com/trailblazer/trailblazer.github.io)
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'roar', github: 'trailblazer/roar', branch: 'master'
6
+
7
+ gem 'minitest-line'
8
+ gem 'minitest-reporters'
9
+ gem 'pry'
10
+
11
+ gem 'json_spec', require: nil
@@ -0,0 +1,20 @@
1
+ Note: If you have a question about Roar, would like help using
2
+ Roar, want to request a feature, or do anything else other than
3
+ submit a bug report, please use the Trailblazer gitter channel.
4
+
5
+ ### Complete Description of Issue
6
+
7
+
8
+ ### Steps to reproduce
9
+
10
+
11
+ ### Expected behavior
12
+ Tell us what should happen
13
+
14
+ ### Actual behavior
15
+ Tell us what happens instead
16
+
17
+ ### System configuration
18
+ **Roar version**:
19
+
20
+ ### Full Backtrace of Exception (if any)
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 - 2017 Nick Sutterer and the roar contributors
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,127 @@
1
+ # Roar JSON API
2
+
3
+ _Resource-Oriented Architectures in Ruby._
4
+
5
+ [![Gitter Chat](https://badges.gitter.im/trailblazer/chat.svg)](https://gitter.im/trailblazer/chat)
6
+ [![TRB Newsletter](https://img.shields.io/badge/TRB-newsletter-lightgrey.svg)](http://trailblazer.to/newsletter/)
7
+ [![Build Status](https://travis-ci.org/trailblazer/roar-jsonapi.svg?branch=master)](https://travis-ci.org/trailblazer/roar-jsonapi)
8
+ [![Gem Version](https://badge.fury.io/rb/roar-jsonapi.svg)](http://badge.fury.io/rb/roar-jsonapi)
9
+
10
+ Roar JSON API provides support for [JSON API](http://jsonapi.org/), a specification for building APIs in JSON. It can render _and_ parse singular and collection documents.
11
+
12
+ ### Resource
13
+
14
+ A minimal representation of a Resource can be defined as follows:
15
+
16
+ ```ruby
17
+ require 'roar/json/json_api'
18
+
19
+ class SongsRepresenter < Roar::Decorator
20
+ include Roar::JSON::JSONAPI.resource :songs
21
+
22
+ attributes do
23
+ property :title
24
+ end
25
+ end
26
+ ```
27
+
28
+ Properties (or attributes) of the represented model are defined within an
29
+ `attributes` block.
30
+
31
+ An `id` property will automatically defined when using Roar JSON API.
32
+
33
+ ### Relationships
34
+
35
+ To define relationships, use `::has_one` or `::has_many` with either an inline
36
+ or a standalone representer (specified with the `extend:` or `decorates:` option).
37
+
38
+ ```ruby
39
+ class SongsRepresenter < Roar::Decorator
40
+ include Roar::JSON::JSONAPI.resource :songs
41
+
42
+ has_one :album do
43
+ property :title
44
+ end
45
+
46
+ has_many :musicians, extend: MusicianRepresenter
47
+ end
48
+ ```
49
+
50
+ ### Meta information
51
+
52
+ Meta information can be included into rendered singular and collection documents in two ways.
53
+
54
+ You can define meta information on your collection object and then let Roar compile it.
55
+
56
+ ```ruby
57
+ class SongsRepresenter < Roar::Decorator
58
+ include Roar::JSON::JSONAPI.resource :songs
59
+
60
+ meta toplevel: true do
61
+ property :page
62
+ property :total
63
+ end
64
+ end
65
+ ```
66
+
67
+ Your collection object must expose the respective methods.
68
+
69
+ ```ruby
70
+ collection.page #=> 1
71
+ collection.total #=> 12
72
+ ```
73
+
74
+ This will render the `{"meta": {"page": 1, "total": 12}}` hash into the JSON API document.
75
+
76
+ Alternatively, you can provide meta information as a hash when rendering. Any values also defined on your object will be overriden.
77
+
78
+ ```ruby
79
+ collection.to_json(meta: {page: params["page"], total: collection.size})
80
+ ```
81
+
82
+ Both methods work for singular documents too.
83
+
84
+ ```ruby
85
+ class SongsRepresenter < Roar::Decorator
86
+ include Roar::JSON::JSONAPI.resource :songs
87
+
88
+ meta do
89
+ property :label
90
+ property :format
91
+ end
92
+ end
93
+ ```
94
+
95
+ ```ruby
96
+ song.to_json(meta: { label: 'EMI' })
97
+ ```
98
+
99
+ If you need more functionality (and parsing), please let us know.
100
+
101
+ ### Usage
102
+
103
+ As JSON API per definition can represent singular models and collections you have two entry points.
104
+
105
+ ```ruby
106
+ SongsRepresenter.prepare(Song.find(1)).to_json
107
+ SongsRepresenter.prepare(Song.new).from_json("..")
108
+ ```
109
+
110
+ Singular models can use the representer module directly.
111
+
112
+ ```ruby
113
+ SongsRepresenter.for_collection.prepare([Song.find(1), Song.find(2)]).to_json
114
+ SongsRepresenter.for_collection.prepare([Song.new, Song.new]).from_json("..")
115
+ ```
116
+
117
+
118
+ Parsing currently works great with singular documents - for collections, we are still working out how to encode the application semantics. Feel free to help.
119
+
120
+ ## Support
121
+
122
+ Questions? Need help? Free 1st Level Support on irc.freenode.org#roar !
123
+ We also have a [mailing list](https://groups.google.com/forum/?fromgroups#!forum/roar-talk), yiha!
124
+
125
+ ## License
126
+
127
+ Roar is released under the [MIT License](http://www.opensource.org/licenses/MIT).
@@ -0,0 +1,12 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rake/testtask'
5
+
6
+ task default: [:test]
7
+
8
+ Rake::TestTask.new(:test) do |test|
9
+ test.libs << 'test'
10
+ test.test_files = FileList['test/**/*_test.rb']
11
+ test.verbose = true
12
+ end
@@ -0,0 +1,156 @@
1
+ require 'roar/json'
2
+ require 'roar/decorator'
3
+ require 'set'
4
+
5
+ require 'roar/json/json_api/member_name'
6
+
7
+ require 'roar/json/json_api/defaults'
8
+ require 'roar/json/json_api/meta'
9
+ require 'roar/json/json_api/declarative'
10
+ require 'roar/json/json_api/for_collection'
11
+ require 'roar/json/json_api/options'
12
+ require 'roar/json/json_api/document'
13
+
14
+ module Roar
15
+ module JSON
16
+ module JSONAPI
17
+ # Include to define a JSON API Resource and make API methods available to
18
+ # your `Roar::Decorator`.
19
+ #
20
+ # @api public
21
+ class Resource < Module
22
+ # @param [Symbol, String] type type name of this resource.
23
+ # @option options [Symbol] :id_key custom ID key for this resource.
24
+ def initialize(type, options = {})
25
+ @type = type
26
+ @id_key = options.fetch(:id_key, :id)
27
+ end
28
+
29
+ private
30
+
31
+ # Hook called when module is included
32
+ #
33
+ # @param [Class,Module] base
34
+ # the module or class including JSONAPI
35
+ #
36
+ # @return [undefined]
37
+ #
38
+ # @api private
39
+ # @see http://www.ruby-doc.org/core/Module.html#method-i-included
40
+ def included(base)
41
+ base.send(:include, JSONAPI::Mixin)
42
+ base.type(@type)
43
+ base.property(@id_key, as: :id, render_filter: ->(input, _opts) {
44
+ input.to_s
45
+ })
46
+ end
47
+ end
48
+
49
+ # Include to define a JSON API Resource and make API methods available to
50
+ # your `Roar::Decorator`.
51
+ #
52
+ # @example Basic Usage
53
+ # class SongsRepresenter < Roar::Decorator
54
+ # include Roar::JSON::JSONAPI.resource :songs
55
+ # end
56
+ #
57
+ # @example Custom ID key
58
+ # class SongsRepresenter < Roar::Decorator
59
+ # include Roar::JSON::JSONAPI.resource :songs, id_key: :song_id
60
+ # end
61
+ #
62
+ # @param (see Resource.initialize)
63
+ # @option options (see Resource.initialize)
64
+ #
65
+ # @see Mixin
66
+ # @api public
67
+ def self.resource(type, options = {})
68
+ Resource.new(type, options)
69
+ end
70
+
71
+ # Include to make API methods available to your `Roar::Decorator`.
72
+ #
73
+ # Unlike {Resource}, you must define a `type` (by calling
74
+ # {Declarative#type}) and `id` property separately.
75
+ #
76
+ # @example Basic Usage
77
+ # class SongsRepresenter < Roar::Decorator
78
+ # include Roar::JSON::JSONAPI::Mixin
79
+ #
80
+ # type :songs
81
+ # property :id
82
+ # end
83
+ #
84
+ # @see Resource
85
+ # @api semi-public
86
+ module Mixin
87
+ # Hook called when module is included
88
+ #
89
+ # @param [Class,Module] base
90
+ # the module or class including JSONAPI
91
+ #
92
+ # @return [undefined]
93
+ #
94
+ # @api private
95
+ # @see http://www.ruby-doc.org/core/Module.html#method-i-included
96
+ def self.included(base)
97
+ base.class_eval do
98
+ feature Roar::JSON
99
+ feature Roar::Hypermedia
100
+ feature JSONAPI::Defaults, JSONAPI::Meta
101
+ extend JSONAPI::Declarative
102
+ extend JSONAPI::ForCollection
103
+ include JSONAPI::Document
104
+ self.representation_wrap = :data
105
+
106
+ nested :relationships do
107
+ end
108
+
109
+ nested :included do
110
+ def to_hash(*)
111
+ super.flat_map { |_, resource| resource }
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
117
+
118
+ # @api private
119
+ module Renderer
120
+ class Links
121
+ def call(res, _options)
122
+ tuples = (res.delete('links') || []).collect { |link|
123
+ [JSONAPI::MemberName.(link['rel']), link['href']]
124
+ }
125
+
126
+ ::Hash[tuples] # NOTE: change to tuples.to_h when dropping < 2.1.
127
+ end
128
+ end
129
+ end
130
+
131
+ # @api private
132
+ module Fragment
133
+ Included = ->(included, options) do
134
+ return unless included && included.any?
135
+ return if options[:included] == false
136
+
137
+ type_and_id_seen = Set.new
138
+
139
+ included = included.select { |object|
140
+ type_and_id_seen.add? [object['type'], object['id']]
141
+ }
142
+
143
+ included
144
+ end
145
+ end
146
+ end
147
+
148
+ # @api private
149
+ module HashUtils
150
+ def store_if_any(hash, key, value)
151
+ hash[key] = value if value && value.any?
152
+ end
153
+ module_function :store_if_any
154
+ end
155
+ end
156
+ end