shamu 0.0.2 → 0.0.3

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: 27e560182b114ef221743131ca89ac18601cfbf7
4
- data.tar.gz: c6fd668c63413a9d45cefe73b87a587240ee5c8c
3
+ metadata.gz: 027f0ea99b484c02d9986999b39f3025dee4b4a3
4
+ data.tar.gz: 0eb00f3878a9718c979e511e8930cf81d8d708e8
5
5
  SHA512:
6
- metadata.gz: 31814221203809e5be4e532732c4f01d0f6c2583dc197bf4025efb8f1ae0e6e69c45707d5b7d553ea87e555767bf56a7efc29c910b1ea1245ac62283f3e5602d
7
- data.tar.gz: 915d74f223c593d04dc7b5d79629d7207d26fd5238956c52bf43f03cfd2bf20915ba59fedafd6249b19a0c00792952aa9e4d62638af880fe0d7e5d13702ce7aa
6
+ metadata.gz: 75946cc4efced52d7a3cf58bb673c75cdd2d9a7aee479b91f3fff4c96d485b74319f07c22345c616075a598948ee861eecd816046aefd37f9761321981c3d11e
7
+ data.tar.gz: 63784d0e8b20db671ba1563c19146ecea4e2fa3728098fc1a79db42e8ef2ebf57a7e68716c9aa349676dff841b6c92f4c73fc81f660df3bbe3fca4d1a8b953ba
data/.rubocop.yml CHANGED
@@ -79,7 +79,10 @@ Style/MultilineBlockChain:
79
79
  Enabled: false
80
80
 
81
81
  Style/OptionHash:
82
- Enabled: true
82
+ Enabled: true
83
+
84
+ Style/ParallelAssignment:
85
+ Enabled: false
83
86
 
84
87
  Style/RegexpLiteral:
85
88
  Enabled: false
@@ -111,6 +114,9 @@ Style/TrailingBlankLines:
111
114
  Style/TrailingCommaInLiteral:
112
115
  Enabled: false
113
116
 
117
+ Style/TrivialAccessors:
118
+ Enabled: false
119
+
114
120
  Style/UnneededInterpolation:
115
121
  Enabled: false
116
122
 
data/README.md CHANGED
@@ -23,8 +23,7 @@ Have a whale of a good time adding Service Oriented Architecture to your ruby pr
23
23
  - {Shamu::Auditing}
24
24
  - {Shamu::Features}
25
25
  - {Shamu::Rails}
26
-
27
-
26
+ - {Shamu::JsonApi}
28
27
 
29
28
  # Dependency Injection
30
29
 
@@ -158,7 +158,7 @@ module Shamu
158
158
 
159
159
  # @param [String] path of the default config file.
160
160
  # @return [String]
161
- def default_config_path=( path ) # rubocop:disable Style/TrivialAccessors
161
+ def default_config_path=( path )
162
162
  @default_config_path = path
163
163
  end
164
164
  end
@@ -0,0 +1 @@
1
+ http://jsonapi.org
@@ -0,0 +1,67 @@
1
+ module Shamu
2
+ module JsonApi
3
+
4
+ # Used by a {Serilaizer} to write fields and relationships
5
+ class BaseBuilder
6
+
7
+ # @param [Context] context the current serialization context.
8
+ def initialize( context )
9
+ @context = context
10
+ @output = {}
11
+ end
12
+
13
+ # @overload identifier( type, id )
14
+ # @param [String] type of the resource.
15
+ # @param [Object] id of the resource.
16
+ # @overload identifier( resource )
17
+ # @param [#json_api_type,#id] resource an object that responds to `json_api_type` and `id`
18
+ #
19
+ # Write a resource linkage info.
20
+ #
21
+ # @return [void]
22
+ def identifier( type, id = nil )
23
+ type, id = type.json_api_type, type.id if type.respond_to? :json_api_type
24
+
25
+ output[:type] = type.to_s
26
+ output[:id] = id.to_s
27
+ end
28
+
29
+ # Write a link to another resource.
30
+ #
31
+ # @param [String,Symbol] name of the link.
32
+ # @param [String] url
33
+ # @param [Hash] meta optional additional meta information.
34
+ # @return [void]
35
+ def link( name, url, meta: nil )
36
+ links = ( output[:links] ||= {} )
37
+
38
+ if meta # rubocop:disable Style/ConditionalAssignment
39
+ links[ name.to_sym ] = { href: url, meta: meta }
40
+ else
41
+ links[ name.to_sym ] = url
42
+ end
43
+ end
44
+
45
+ # Add a meta field.
46
+ # @param [String,Symbol] name of the meta field.
47
+ # @param [Object] vlaue that can be converted to a JSON primitive type.
48
+ # @return [void]
49
+ def meta( name, value )
50
+ meta = ( output[:meta] ||= {} )
51
+ meta[ name.to_sym ] = value
52
+ end
53
+
54
+ # @return [Hash] the results output as JSON safe hash.
55
+ def compile
56
+ fail JsonApi::IncompleteResourceError unless output[:type]
57
+ output
58
+ end
59
+
60
+ private
61
+
62
+ attr_reader :context
63
+ attr_reader :output
64
+
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,69 @@
1
+ module Shamu
2
+ module JsonApi
3
+ class Context
4
+
5
+ def initialize( fields: nil )
6
+ @included_resources = {}
7
+ @all_resources = Set.new
8
+ @fields = parse_fields( fields )
9
+ end
10
+
11
+ # Add an included resource for a compound response.
12
+ #
13
+ # @param [Object] resource to be serialized.
14
+ # @param [Serializer] the serializer to use to serialize the object. If
15
+ # not provided a default {Serializer} will be chosen.
16
+ # @return [resource]
17
+ # @yield (builder)
18
+ # @yieldparam [ResourceBuilder] builder to write embedded resource to.
19
+ def include_resource( resource, serializer = nil, &block )
20
+ return if all_resources.include?( resource )
21
+
22
+ all_resources << resource
23
+ included_resources[resource] ||= { serializer: serializer, block: block }
24
+ end
25
+
26
+ # Collects all the currently included resources and resets the queue.
27
+ def collect_included_resources
28
+ included = included_resources.dup
29
+ @included_resources = {}
30
+ included
31
+ end
32
+
33
+ # @return [Boolean] true if there are any pending included resources.
34
+ def included_resources?
35
+ included_resources.any?
36
+ end
37
+
38
+ # Check to see if the field should be included in the JSON API output.
39
+ #
40
+ # @param [Symbol] type the resource type in question.
41
+ # @param [Symbol] name of the field on the resouce in question.
42
+ # @return [Boolean] true if the
43
+ def include_field?( type, name )
44
+ return true unless type_fields = fields[ type ]
45
+
46
+ type_fields.include?( name )
47
+ end
48
+
49
+ private
50
+
51
+ attr_reader :all_resources
52
+ attr_reader :included_resources
53
+ attr_reader :fields
54
+
55
+ def parse_fields( raw )
56
+ return {} unless raw
57
+
58
+ raw.each_with_object( {} ) do |(type, fields), parsed|
59
+ fields = fields.split( "," ) if fields.is_a?( String )
60
+
61
+ parsed[ type.to_sym ] = fields.map do |field|
62
+ field = field.strip if field.is_a? String
63
+ field.to_sym
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,10 @@
1
+ module Shamu
2
+ module JsonApi
3
+
4
+ # A {Serializer} that can serialize all of the public attributes of an
5
+ # {Entities::Entity}.
6
+ class EntitySerializer < Serializer
7
+
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,29 @@
1
+ require "i18n"
2
+
3
+ module Shamu
4
+
5
+ module JsonApi
6
+ # A generic error class for problems with shamu JSON API.
7
+ class Error < Shamu::Error
8
+ private
9
+
10
+ def translation_scope
11
+ super.dup.insert( 1, :json_api )
12
+ end
13
+
14
+ end
15
+
16
+ # Raised if an {ResourceBuilder#identifier} was not built.
17
+ class IncompleteResourceError < Error
18
+ def initialize( message = :incomplete_resource )
19
+ super
20
+ end
21
+ end
22
+
23
+ class IdentifierRequiredError < Error
24
+ def initialize( message = :identifier_required )
25
+ super
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,78 @@
1
+ module Shamu
2
+ module JsonApi
3
+
4
+ # Build an error response object.
5
+ class ErrorBuilder
6
+
7
+ def initialize
8
+ @output = { id: SecureRandom.uuid }
9
+ end
10
+
11
+ # @param [String] id unique id for this occurrence of the error.
12
+ def id( id )
13
+ output[:id] = id
14
+ end
15
+
16
+ # Summary of the error.
17
+ # @param [Integer] http_status code.
18
+ # @param [String,Symbol] code application specific code for the error.
19
+ # @param [String] human friendly title for the error.
20
+ def summary( http_status, code, title = nil )
21
+ output[:status] = http_status.to_s
22
+ output[:code] = code.to_s
23
+ output[:title] = title || code.to_s.titleize
24
+ end
25
+
26
+ # Summarize an exception as an error.
27
+ # @param [Exception] exception
28
+ # @param [Integer] http_status code. Default 400.
29
+ def exception( exception, http_status = nil )
30
+ http_status ||= 400
31
+
32
+ name = exception.class.name.demodulize.gsub( /Error$/, "" )
33
+ summary http_status, name.underscore, name.titleize
34
+ detail exception.message
35
+ end
36
+
37
+ # @return [String] message details about the error.
38
+ def detail( message )
39
+ output[:detail] = message
40
+ end
41
+
42
+ # Write a link to error information.
43
+ #
44
+ # @param [String,Symbol] name of the link.
45
+ # @param [String] url
46
+ # @param [Hash] meta optional additional meta information.
47
+ # @return [void]
48
+ def link( name, url, meta: nil )
49
+ links = ( output[:links] ||= {} )
50
+
51
+ if meta # rubocop:disable Style/ConditionalAssignment
52
+ links[ name.to_sym ] = { href: url, meta: meta }
53
+ else
54
+ links[ name.to_sym ] = url
55
+ end
56
+ end
57
+
58
+ # Add a meta field.
59
+ # @param [String,Symbol] name of the meta field.
60
+ # @param [Object] value that can be converted to a JSON primitive type.
61
+ # @return [void]
62
+ def meta( name, value )
63
+ meta = ( output[:meta] ||= {} )
64
+ meta[ name.to_sym ] = value
65
+ end
66
+
67
+ # @return [Hash] the results output as JSON safe hash.
68
+ def compile
69
+ output
70
+ end
71
+
72
+ private
73
+
74
+ attr_reader :output
75
+
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,16 @@
1
+ require "shamu/json_api/base_builder"
2
+
3
+ module Shamu
4
+ module JsonApi
5
+
6
+ # Build a relationship from one resource to another.
7
+ class RelationshipBuilder < BaseBuilder
8
+
9
+ # (see Context#include_resource)
10
+ def include_resource( resource, serializer = nil, &block )
11
+ context.include_resource resource, serializer, &block
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,81 @@
1
+ require "shamu/json_api/base_builder"
2
+
3
+ module Shamu
4
+ module JsonApi
5
+
6
+ # Used by a {Serilaizer} to write fields and relationships
7
+ class ResourceBuilder < BaseBuilder
8
+
9
+ # @overload attribute( attributes )
10
+ # @param [Hash] attributes to write.
11
+ # @overload attribute( name, value )
12
+ # @param [String, Symbol] name of the attribute.
13
+ # @param [Object] value that can be persited to a JSON primitive value.
14
+ #
15
+ # Write one or more attributes to the output.
16
+ #
17
+ # @return [void]
18
+ def attribute( name_or_hash, value = nil )
19
+ require_identifier!
20
+
21
+ if value
22
+ add_attribute name_or_hash, value
23
+ else
24
+ name_or_hash.each do |n, v|
25
+ add_attribute n, v
26
+ end
27
+ end
28
+ end
29
+
30
+ # Build a relationship reference.
31
+ #
32
+ # ```
33
+ # relationship :author do |builder|
34
+ # builder.identifier author
35
+ # builder.link :related, author_url author
36
+ # builder.link :self, book_author_url( book, author )
37
+ # end
38
+ # ```
39
+ #
40
+ # @param [String,Symbol] name of the relationship.
41
+ # @return [void]
42
+ # @yield (builder)
43
+ # @yieldparam [RelationshipBuilder] builder used to define the properties
44
+ # of the relationship.
45
+ def relationship( name, &block )
46
+ require_identifier!
47
+
48
+ return unless context.include_field?( type, name )
49
+
50
+ builder = RelationshipBuilder.new( context )
51
+ yield builder
52
+
53
+ relationships = ( output[:relationships] ||= {} )
54
+ relationships[ name.to_sym ] = builder.compile
55
+ end
56
+
57
+ # (see BaseBuilder#identifier)
58
+ def identifier( * )
59
+ super.tap do
60
+ @type = output[:type]
61
+ end
62
+ end
63
+
64
+ private
65
+
66
+ attr_reader :type
67
+
68
+ def require_identifier!
69
+ fail IdentifierRequiredError unless @type
70
+ end
71
+
72
+ def add_attribute( name, value )
73
+ return unless context.include_field?( type, name )
74
+
75
+ attributes = ( output[:attributes] ||= {} )
76
+ attributes[ name.to_sym ] = value
77
+ end
78
+
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,99 @@
1
+ module Shamu
2
+ module JsonApi
3
+
4
+ # Build a JSON API response from one or more resources.
5
+ class Response < BaseBuilder
6
+
7
+ # Output a single resource as the response data.
8
+ # @param [Object] resource to write.
9
+ # @param [Serializer] serializer used to write the resource state.
10
+ # @yield (builder)
11
+ # @yieldparam [ResourceBuilder] builder used write the resources fields
12
+ # and meta.
13
+ #
14
+ # @return [void]
15
+ def resource( resource, serializer = nil, &block )
16
+ output[:data] = build_resource( resource, serializer, &block )
17
+ end
18
+
19
+ # Output a single resource as the response data.
20
+ #
21
+ # @param [Enumerable<Object>] resources to write.
22
+ # @param [Serializer] serializer used to write the resource state.
23
+ # @yield (builder, resource)
24
+ # @yieldparam [ResourceBuilder] builder used write the resources fields
25
+ # and meta.
26
+ # @yieldparam [Object] resource being written.
27
+ # @return [void]
28
+ def resources( collection, serializer = nil, &block )
29
+ output[:data] =
30
+ collection.map do |resource|
31
+ build_resource resource, serializer, &block
32
+ end
33
+ end
34
+
35
+ # @overload error( exception, http_status = nil )
36
+ # @param (see ErrorBuilder#exception)
37
+ # @overload error( &block )
38
+ # @yield (builder)
39
+ # @yieldparam [ErrorBuilder] builder used to describe the error.
40
+ #
41
+ # @return [void]
42
+ def error( exception = nil, http_status = nil, &block )
43
+ builder = ErrorBuilder.new
44
+
45
+ if block_given?
46
+ yield builder
47
+ else
48
+ builder.exception( exception, http_status )
49
+ end
50
+
51
+ errors = ( output[:errors] ||= [] )
52
+ errors << builder.compile
53
+ end
54
+
55
+ # (see BaseBuilder#compile)
56
+ def compile
57
+ @compiled ||= begin
58
+ compiled = output.dup
59
+ compiled[:jsonapi] = { version: "1.0" }
60
+
61
+ while context.included_resources?
62
+ included = ( compiled[ :included ] ||= [] )
63
+ context.collect_included_resources.each do |resource, options|
64
+ included << build_resource( resource, options[:serializer], &options[:block] )
65
+ end
66
+ end
67
+
68
+ compiled
69
+ end
70
+ end
71
+
72
+ def to_json
73
+ compile.to_json
74
+ end
75
+
76
+ def to_s
77
+ compile.to_s
78
+ end
79
+
80
+ private :identifier
81
+
82
+ private
83
+
84
+ def build_resource( resource, serializer, &block )
85
+ fail "A block is required if no serializer is given" if !serializer && !block_given?
86
+
87
+ builder = ResourceBuilder.new( context )
88
+ if serializer
89
+ serializer.serialize( builder )
90
+ else
91
+ yield builder
92
+ end
93
+
94
+ builder.compile
95
+ end
96
+
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,33 @@
1
+ module Shamu
2
+ module JsonApi
3
+
4
+ # Serialize an object to a JSON API stream.
5
+ class Serializer
6
+
7
+ # @param [Object] resource to be serialized.
8
+ def initialize( resource )
9
+ @resource = resource
10
+ end
11
+
12
+ # Serialize the {#resource} to the builder.
13
+ # @param [ResourceBuilder] builder to write to.
14
+ # @return [void]
15
+ def serialize( builder )
16
+ end
17
+
18
+ private
19
+
20
+ attr_reader :resource
21
+
22
+ class << self
23
+
24
+ # Find a {Serializer} that knows how to serialize the given resource.
25
+ # @param [Object] resource to serialize.
26
+ # @return [Serializer]
27
+ def find( resource )
28
+ end
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,8 @@
1
+ module Shamu
2
+ module JsonApi
3
+
4
+ # Add the ability to support JSON API serialization.
5
+ module Support
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,13 @@
1
+ module Shamu
2
+ # {include:file:lib/shamu/json_api/README.md}
3
+ module JsonApi
4
+ require "shamu/json_api/context"
5
+ require "shamu/json_api/relationship_builder"
6
+ require "shamu/json_api/resource_builder"
7
+ require "shamu/json_api/response"
8
+ require "shamu/json_api/serializer"
9
+ require "shamu/json_api/support"
10
+ require "shamu/json_api/error"
11
+ require "shamu/json_api/error_builder"
12
+ end
13
+ end
@@ -24,4 +24,9 @@ en:
24
24
 
25
25
  features:
26
26
  errors:
27
- retired_toggle_checked: "The `%{name}` toggle retired at `%{retire_at}` and cannot be checked anymore."
27
+ retired_toggle_checked: "The `%{name}` toggle retired at `%{retire_at}` and cannot be checked anymore."
28
+
29
+ json_api:
30
+ errors:
31
+ incomplete_resource: "`identifier` was not called to define the type and id of the resource"
32
+ identifier_resource: "`identifier` must be called before defining any fields"
data/lib/shamu/version.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  module Shamu
3
3
  # The primary version number
4
- VERSION_NUMBER = "0.0.2".freeze
4
+ VERSION_NUMBER = "0.0.3".freeze
5
5
 
6
6
  # Version suffix such as 'beta' or 'alpha'
7
7
  VERSION_SUFFIX = "".freeze
data/lib/shamu.rb CHANGED
@@ -15,6 +15,7 @@ module Shamu
15
15
  require "shamu/events"
16
16
  require "shamu/sessions"
17
17
  require "shamu/features"
18
+ require "shamu/json_api"
18
19
  require "shamu/to_model_id_extension"
19
20
  require "shamu/to_bool_extension"
20
21
 
@@ -0,0 +1,42 @@
1
+ require "spec_helper"
2
+
3
+ describe Shamu::JsonApi::BaseBuilder do
4
+ let( :context ) { Shamu::JsonApi::Context.new }
5
+ let( :builder ) { Shamu::JsonApi::BaseBuilder.new( context ) }
6
+
7
+ before( :each ) do
8
+ builder.identifier "example", 1
9
+ end
10
+
11
+ describe "#identifier" do
12
+ it "writes type and id" do
13
+ builder.identifier "spec", 5
14
+
15
+ expect( builder.compile ).to include type: "spec", id: "5"
16
+ end
17
+ end
18
+
19
+ describe "#link" do
20
+ it "adds a link" do
21
+ builder.link :self, "http://localhost"
22
+
23
+ expect( builder.compile ).to include links: { self: "http://localhost" }
24
+ end
25
+ end
26
+
27
+ describe "#meta" do
28
+ it "adds the meta data" do
29
+ builder.meta :updated, "today"
30
+
31
+ expect( builder.compile ).to include meta: { updated: "today" }
32
+ end
33
+ end
34
+
35
+ describe "#compile" do
36
+ it "fails if identifier has not been specified" do
37
+ expect do
38
+ Shamu::JsonApi::BaseBuilder.new( context ).compile
39
+ end.to raise_error Shamu::JsonApi::IncompleteResourceError
40
+ end
41
+ end
42
+ end
File without changes
@@ -0,0 +1,31 @@
1
+ require "spec_helper"
2
+
3
+ describe Shamu::JsonApi::Context do
4
+ it "parses comma deliminated fields" do
5
+ context = Shamu::JsonApi::Context.new fields: { "user" => "name, email," }
6
+
7
+ expect( context.send( :fields ) ).to eq user: [:name, :email]
8
+ end
9
+
10
+ it "accepts array of fields" do
11
+ context = Shamu::JsonApi::Context.new fields: { "user" => [ "name", "email" ] }
12
+
13
+ expect( context.send( :fields ) ).to eq user: [:name, :email]
14
+ end
15
+
16
+ describe "#include_field?" do
17
+ let( :context ) { Shamu::JsonApi::Context.new( fields: { "user": "name,email" } ) }
18
+
19
+ it "is true for unfiltered" do
20
+ expect( context.include_field?( :order, :number ) ).to be_truthy
21
+ end
22
+
23
+ it "is true for filtered with field" do
24
+ expect( context.include_field?( :user, :name ) ).to be_truthy
25
+ end
26
+
27
+ it "is false for filtered without field" do
28
+ expect( context.include_field?( :user, :birthdate ) ).not_to be_truthy
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,31 @@
1
+ require "spec_helper"
2
+
3
+ describe Shamu::JsonApi::ErrorBuilder do
4
+ let( :builder ) { Shamu::JsonApi::ErrorBuilder.new }
5
+
6
+ describe "#summary" do
7
+ it "infers title" do
8
+ builder.summary 422, :not_allowed
9
+
10
+ expect( builder.compile ).to include title: "Not Allowed"
11
+ end
12
+ end
13
+
14
+ describe "#exception" do
15
+ before( :each ) do
16
+ builder.exception NotImplementedError.new( "Nope, we haven't done that yet" )
17
+ end
18
+
19
+ it "applies message to details" do
20
+ expect( builder.compile ).to include detail: "Nope, we haven't done that yet"
21
+ end
22
+
23
+ it "applies class name as code" do
24
+ expect( builder.compile ).to include code: "not_implemented"
25
+ end
26
+
27
+ it "applies class name as title" do
28
+ expect( builder.compile ).to include title: "Not Implemented"
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,5 @@
1
+ require "spec_helper"
2
+
3
+ describe Shamu::JsonApi::RelationshipBuilder do
4
+
5
+ end
@@ -0,0 +1,52 @@
1
+ require "spec_helper"
2
+
3
+ describe Shamu::JsonApi::RelationshipBuilder do
4
+ let( :context ) { Shamu::JsonApi::Context.new }
5
+ let( :builder ) { Shamu::JsonApi::ResourceBuilder.new( context ) }
6
+
7
+ before( :each ) do
8
+ builder.identifier "example", 1
9
+ end
10
+
11
+ describe "#attribute" do
12
+ it "adds to the attributes node" do
13
+ builder.attribute name: "Jim"
14
+
15
+ expect( builder.compile ).to include attributes: { name: "Jim" }
16
+ end
17
+
18
+ it "adds a single name, value pair" do
19
+ builder.attribute :name, "Jim"
20
+
21
+ expect( builder.compile ).to include attributes: { name: "Jim" }
22
+ end
23
+
24
+ it "excludes filtered attributes" do
25
+ allow( context ).to receive( :include_field? ).and_return false
26
+
27
+ builder.attribute name: "Nope"
28
+ expect( builder.compile ).not_to include attributes: { name: "Nope" }
29
+ end
30
+ end
31
+
32
+ describe "#relationship" do
33
+ it "adds a relationship" do
34
+ builder.relationship :parent do |rel|
35
+ rel.identifier :example, 5
36
+ end
37
+
38
+ expect( builder.compile ).to include relationships: { parent: kind_of( Hash ) }
39
+ end
40
+
41
+ it "excludes filtered relationships" do
42
+ allow( context ).to receive( :include_field? ).and_return false
43
+
44
+ builder.relationship :parent do |rel|
45
+ rel.identifier :example, 5
46
+ end
47
+
48
+ expect( builder.compile ).not_to include relationships: { parent: kind_of( Hash ) }
49
+ end
50
+ end
51
+
52
+ end
@@ -0,0 +1,42 @@
1
+ require "spec_helper"
2
+
3
+ describe Shamu::JsonApi::Response do
4
+ let( :context ) { Shamu::JsonApi::Context.new }
5
+ let( :response ) { Shamu::JsonApi::Response.new context }
6
+
7
+ it "uses serializer if given" do
8
+ serializer = double Shamu::JsonApi::Serializer
9
+ expect( serializer ).to receive( :serialize ) do |builder|
10
+ builder.identifier :response, 9
11
+ end
12
+
13
+ response.resource double, serializer
14
+ end
15
+
16
+ it "expects a block if no serializer" do
17
+ expect do
18
+ response.resource double
19
+ end.to raise_error /block/
20
+ end
21
+
22
+ it "appends included resources" do
23
+
24
+ response.resource double do |builder|
25
+ builder.identifier :example, 4
26
+ builder.relationship :parent do |rel|
27
+ rel.identifier :suite, 10
28
+ rel.include_resource double do |res|
29
+ res.identifier :suite, 10
30
+ end
31
+ end
32
+ end
33
+
34
+ expect( response.compile ).to include included: [ hash_including( type: "suite" ) ]
35
+ end
36
+
37
+ it "includes errors" do
38
+ response.error NotImplementedError.new
39
+
40
+ expect( response.compile ).to include errors: [ hash_including( code: "not_implemented" ) ]
41
+ end
42
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shamu
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Alexander
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-17 00:00:00.000000000 Z
11
+ date: 2016-04-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -269,6 +269,18 @@ files:
269
269
  - lib/shamu/features/support.rb
270
270
  - lib/shamu/features/toggle.rb
271
271
  - lib/shamu/features/toggle_codec.rb
272
+ - lib/shamu/json_api.rb
273
+ - lib/shamu/json_api/README.md
274
+ - lib/shamu/json_api/base_builder.rb
275
+ - lib/shamu/json_api/context.rb
276
+ - lib/shamu/json_api/entity_serializer.rb
277
+ - lib/shamu/json_api/error.rb
278
+ - lib/shamu/json_api/error_builder.rb
279
+ - lib/shamu/json_api/relationship_builder.rb
280
+ - lib/shamu/json_api/resource_builder.rb
281
+ - lib/shamu/json_api/response.rb
282
+ - lib/shamu/json_api/serializer.rb
283
+ - lib/shamu/json_api/support.rb
272
284
  - lib/shamu/locale/en.yml
273
285
  - lib/shamu/logger.rb
274
286
  - lib/shamu/rack.rb
@@ -363,6 +375,13 @@ files:
363
375
  - spec/lib/shamu/features/support_spec.rb
364
376
  - spec/lib/shamu/features/toggle_codec_spec.rb
365
377
  - spec/lib/shamu/features/toggle_spec.rb
378
+ - spec/lib/shamu/json_api/base_builder_spec.rb
379
+ - spec/lib/shamu/json_api/common_builder_spec.rb
380
+ - spec/lib/shamu/json_api/context_spec.rb
381
+ - spec/lib/shamu/json_api/error_builder_spec.rb
382
+ - spec/lib/shamu/json_api/relationship_builder_spec.rb
383
+ - spec/lib/shamu/json_api/resource_builder_spec.rb
384
+ - spec/lib/shamu/json_api/response_spec.rb
366
385
  - spec/lib/shamu/rack/cookies_middleware_spec.rb
367
386
  - spec/lib/shamu/rack/cookies_spec.rb
368
387
  - spec/lib/shamu/rack/query_params_middleware_spec.rb
@@ -466,6 +485,13 @@ test_files:
466
485
  - spec/lib/shamu/features/support_spec.rb
467
486
  - spec/lib/shamu/features/toggle_codec_spec.rb
468
487
  - spec/lib/shamu/features/toggle_spec.rb
488
+ - spec/lib/shamu/json_api/base_builder_spec.rb
489
+ - spec/lib/shamu/json_api/common_builder_spec.rb
490
+ - spec/lib/shamu/json_api/context_spec.rb
491
+ - spec/lib/shamu/json_api/error_builder_spec.rb
492
+ - spec/lib/shamu/json_api/relationship_builder_spec.rb
493
+ - spec/lib/shamu/json_api/resource_builder_spec.rb
494
+ - spec/lib/shamu/json_api/response_spec.rb
469
495
  - spec/lib/shamu/rack/cookies_middleware_spec.rb
470
496
  - spec/lib/shamu/rack/cookies_spec.rb
471
497
  - spec/lib/shamu/rack/query_params_middleware_spec.rb