roar-jsonapi 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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