jsonapi-realizer 3.0.0 → 4.0.0
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 +4 -4
- data/README.md +10 -14
- data/lib/jsonapi/realizer/action/create.rb +3 -7
- data/lib/jsonapi/realizer/action/create_spec.rb +81 -31
- data/lib/jsonapi/realizer/action/destroy.rb +27 -0
- data/lib/jsonapi/realizer/action/destroy_spec.rb +81 -0
- data/lib/jsonapi/realizer/action/index.rb +2 -4
- data/lib/jsonapi/realizer/action/index_spec.rb +30 -3
- data/lib/jsonapi/realizer/action/show.rb +2 -5
- data/lib/jsonapi/realizer/action/show_spec.rb +30 -3
- data/lib/jsonapi/realizer/action/update.rb +6 -10
- data/lib/jsonapi/realizer/action/update_spec.rb +6 -28
- data/lib/jsonapi/realizer/action.rb +25 -19
- data/lib/jsonapi/realizer/action_spec.rb +8 -6
- data/lib/jsonapi/realizer/adapter/active_record.rb +0 -8
- data/lib/jsonapi/realizer/adapter/memory.rb +0 -15
- data/lib/jsonapi/realizer/adapter.rb +0 -18
- data/lib/jsonapi/realizer/adapter_spec.rb +0 -8
- data/lib/jsonapi/realizer/error.rb +0 -1
- data/lib/jsonapi/realizer/version.rb +1 -1
- data/lib/jsonapi/realizer.rb +2 -0
- metadata +5 -4
- data/lib/jsonapi/realizer/error/too_many_root_properties.rb +0 -9
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 233431a77cbb99ea5b1fb51dc5840217f6041eb79e054e23074dbd84fa26517b
         | 
| 4 | 
            +
              data.tar.gz: 21000506a07d24308f1f22ebb739a3b1e3863d377a1b9ae424fa8b266ff2f44e
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: c8ab9db2090e5c1208c57c27a63ba5959e33aa5fc27bebfd7d5b3b452d2a16c2e0af23b50e5b5dc8fd12738adfdb39edcab3edb70318db235559cc2850b0b5d0
         | 
| 7 | 
            +
              data.tar.gz: d2128c6ddfa8318c441b48e8beb27d785239a8737ccdd9cfa6f758b4de7981247e35680e8643dd636c0f8719fbdbd3a8cb48b243031101c89100a05abf21599d
         | 
    
        data/README.md
    CHANGED
    
    | @@ -69,15 +69,13 @@ class PhotosController < ApplicationController | |
| 69 69 | 
             
              def index
         | 
| 70 70 | 
             
                realization = JSONAPI::Realizer.index(params, headers: request.headers, type: :photos)
         | 
| 71 71 |  | 
| 72 | 
            -
                 | 
| 73 | 
            -
                authorize realization.models
         | 
| 74 | 
            -
             | 
| 75 | 
            -
                # See: pundit for `policy_scope()`
         | 
| 76 | 
            -
                render json: JSONAPI::Serializer.serialize(policy_scope(record), is_collection: true)
         | 
| 72 | 
            +
                render json: JSONAPI::Serializer.serialize(realization.models, is_collection: true)
         | 
| 77 73 | 
             
              end
         | 
| 78 74 | 
             
            end
         | 
| 79 75 | 
             
            ```
         | 
| 80 76 |  | 
| 77 | 
            +
            Notice that we pass `realization.model` to `ProcessPhotosService`, that's because `jsonapi-realizer` doesn't do the act of saving, creating, or destroying! We just ready up the records for you to handle (including errors).
         | 
| 78 | 
            +
             | 
| 81 79 | 
             
            ### Policies
         | 
| 82 80 |  | 
| 83 81 | 
             
            Most times you will want to control what a person sees when they as for your data. We have created interfaces for this use-case and we'll show how you can use pundit (or any PORO) to constrain your in/out.
         | 
| @@ -130,11 +128,16 @@ end | |
| 130 128 | 
             
            ``` ruby
         | 
| 131 129 | 
             
            class PhotosController < ApplicationController
         | 
| 132 130 | 
             
              def index
         | 
| 133 | 
            -
                realization = JSONAPI::Realizer.index( | 
| 131 | 
            +
                realization = JSONAPI::Realizer.index(
         | 
| 132 | 
            +
                  policy(Photo).sanitize(:index, params),
         | 
| 133 | 
            +
                  headers: request.headers,
         | 
| 134 | 
            +
                  type: :posts,
         | 
| 135 | 
            +
                  relation: policy_scope(Photo)
         | 
| 136 | 
            +
                )
         | 
| 134 137 |  | 
| 135 138 | 
             
                # See: pundit for `policy_scope()`
         | 
| 136 139 | 
             
                # See: pundit for `authorize()`
         | 
| 137 | 
            -
                render json: JSONAPI::Serializer.serialize(authorize( | 
| 140 | 
            +
                render json: JSONAPI::Serializer.serialize(authorize(realization.models), is_collection: true)
         | 
| 138 141 | 
             
              end
         | 
| 139 142 | 
             
            end
         | 
| 140 143 | 
             
            ```
         | 
| @@ -152,8 +155,6 @@ An adapter must provide the following interfaces: | |
| 152 155 | 
             
              0. `find_many_via`, describes how to find many models
         | 
| 153 156 | 
             
              0. `assign_attributes_via`, describes how to write a set of properties
         | 
| 154 157 | 
             
              0. `assign_relationships_via`, describes how to write a set of relationships
         | 
| 155 | 
            -
              0. `create_via`, describes how to create the model
         | 
| 156 | 
            -
              0. `update_via`, describes how to update the model
         | 
| 157 158 | 
             
              0. `includes_via`, describes how to eager include related models
         | 
| 158 159 | 
             
              0. `sparse_fields_via`, describes how to only return certain fields
         | 
| 159 160 |  | 
| @@ -173,11 +174,6 @@ class PhotoRealizer | |
| 173 174 | 
             
                model.update_columns(attributes)
         | 
| 174 175 | 
             
              end
         | 
| 175 176 |  | 
| 176 | 
            -
              adapter.create_via do |model|
         | 
| 177 | 
            -
                model.save!
         | 
| 178 | 
            -
                Rails.cache.write(model.cache_key, model)
         | 
| 179 | 
            -
              end
         | 
| 180 | 
            -
             | 
| 181 177 | 
             
              has_one :photographer, as: :profiles
         | 
| 182 178 |  | 
| 183 179 | 
             
              has :title
         | 
| @@ -4,14 +4,11 @@ module JSONAPI | |
| 4 4 | 
             
                  class Create < Action
         | 
| 5 5 | 
             
                    attr_accessor :resource
         | 
| 6 6 |  | 
| 7 | 
            -
                    def initialize(payload:, headers:)
         | 
| 8 | 
            -
                      @payload = payload
         | 
| 9 | 
            -
                      @headers = headers
         | 
| 10 | 
            -
             | 
| 7 | 
            +
                    def initialize(payload:, headers:, scope: nil)
         | 
| 11 8 | 
             
                      raise Error::MissingContentTypeHeader unless headers.key?("Content-Type")
         | 
| 12 | 
            -
                      raise Error::InvalidContentTypeHeader unless headers.fetch("Content-Type") ==  | 
| 9 | 
            +
                      raise Error::InvalidContentTypeHeader unless headers.fetch("Content-Type") == JSONAPI::MEDIA_TYPE
         | 
| 13 10 |  | 
| 14 | 
            -
                      super(payload: payload, headers: headers)
         | 
| 11 | 
            +
                      super(payload: payload, headers: headers, scope: scope)
         | 
| 15 12 |  | 
| 16 13 | 
             
                      @resource = resource_class.new(relation.new)
         | 
| 17 14 |  | 
| @@ -24,7 +21,6 @@ module JSONAPI | |
| 24 21 | 
             
                      adapter.assign_attributes_via_call(resource.model, {id: id}) if id
         | 
| 25 22 | 
             
                      adapter.assign_attributes_via_call(resource.model, attributes)
         | 
| 26 23 | 
             
                      adapter.assign_relationships_via_call(resource.model, relationships)
         | 
| 27 | 
            -
                      adapter.create_via_call(resource.model)
         | 
| 28 24 | 
             
                    end
         | 
| 29 25 |  | 
| 30 26 | 
             
                    def model
         | 
| @@ -4,11 +4,84 @@ RSpec.describe JSONAPI::Realizer::Action::Create do | |
| 4 4 | 
             
              let(:action) { described_class.new(payload: payload, headers: headers) }
         | 
| 5 5 |  | 
| 6 6 | 
             
              describe "#call" do
         | 
| 7 | 
            -
                subject { action.call }
         | 
| 7 | 
            +
                subject { action.tap(&:call) }
         | 
| 8 8 |  | 
| 9 | 
            -
                context "with no top-level data and  | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 9 | 
            +
                context "with no top-level data and no content-type header no accept headers" do
         | 
| 10 | 
            +
                  let(:payload) do
         | 
| 11 | 
            +
                    {}
         | 
| 12 | 
            +
                  end
         | 
| 13 | 
            +
                  let(:headers) do
         | 
| 14 | 
            +
                    {}
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  it "raises an exception" do
         | 
| 18 | 
            +
                    expect {subject}.to raise_exception(JSONAPI::Realizer::Error::MissingContentTypeHeader)
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                context "with no top-level data and good content-type header no accept headers" do
         | 
| 23 | 
            +
                  let(:payload) do
         | 
| 24 | 
            +
                    {}
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
                  let(:headers) do
         | 
| 27 | 
            +
                    {
         | 
| 28 | 
            +
                      "Content-Type" => "application/vnd.api+json",
         | 
| 29 | 
            +
                    }
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  it "raises an exception" do
         | 
| 33 | 
            +
                    expect {subject}.to raise_exception(JSONAPI::Realizer::Error::MissingAcceptHeader)
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                context "with no top-level data and wrong content-type header" do
         | 
| 38 | 
            +
                  let(:payload) do
         | 
| 39 | 
            +
                    {}
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
                  let(:headers) do
         | 
| 42 | 
            +
                    {
         | 
| 43 | 
            +
                      "Content-Type" => "application/json"
         | 
| 44 | 
            +
                    }
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                  it "raises an exception" do
         | 
| 48 | 
            +
                    expect {subject}.to raise_exception(JSONAPI::Realizer::Error::InvalidContentTypeHeader)
         | 
| 49 | 
            +
                  end
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                context "with no top-level data and good content-type header and wrong accept header" do
         | 
| 53 | 
            +
                  let(:payload) do
         | 
| 54 | 
            +
                    {}
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
                  let(:headers) do
         | 
| 57 | 
            +
                    {
         | 
| 58 | 
            +
                      "Content-Type" => "application/vnd.api+json",
         | 
| 59 | 
            +
                      "Accept" => "application/json"
         | 
| 60 | 
            +
                    }
         | 
| 61 | 
            +
                  end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                  it "raises an exception" do
         | 
| 64 | 
            +
                    expect {subject}.to raise_exception(JSONAPI::Realizer::Error::InvalidAcceptHeader)
         | 
| 65 | 
            +
                  end
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                context "with wrong top-level data and good headers" do
         | 
| 69 | 
            +
                  let(:payload) do
         | 
| 70 | 
            +
                    {
         | 
| 71 | 
            +
                      "data" => ""
         | 
| 72 | 
            +
                    }
         | 
| 73 | 
            +
                  end
         | 
| 74 | 
            +
                  let(:headers) do
         | 
| 75 | 
            +
                    {
         | 
| 76 | 
            +
                      "Content-Type" => "application/vnd.api+json",
         | 
| 77 | 
            +
                      "Accept" => "application/vnd.api+json"
         | 
| 78 | 
            +
                    }
         | 
| 79 | 
            +
                  end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                  it "raises an exception" do
         | 
| 82 | 
            +
                    expect {subject}.to raise_exception(JSONAPI::Realizer::Error::MalformedDataRootProperty)
         | 
| 83 | 
            +
                  end
         | 
| 84 | 
            +
                end
         | 
| 12 85 |  | 
| 13 86 | 
             
                context "with a good payload and good headers" do
         | 
| 14 87 | 
             
                  let(:payload) do
         | 
| @@ -44,12 +117,6 @@ RSpec.describe JSONAPI::Realizer::Action::Create do | |
| 44 117 | 
             
                      expect(action.model).to be_a_kind_of(Photo)
         | 
| 45 118 | 
             
                    end
         | 
| 46 119 |  | 
| 47 | 
            -
                    it "assigns the id attribute" do
         | 
| 48 | 
            -
                      subject
         | 
| 49 | 
            -
             | 
| 50 | 
            -
                      expect(action.model).to have_attributes(id: "550e8400-e29b-41d4-a716-446655440000")
         | 
| 51 | 
            -
                    end
         | 
| 52 | 
            -
             | 
| 53 120 | 
             
                    it "assigns the title attribute" do
         | 
| 54 121 | 
             
                      subject
         | 
| 55 122 |  | 
| @@ -68,12 +135,6 @@ RSpec.describe JSONAPI::Realizer::Action::Create do | |
| 68 135 | 
             
                      expect(action.model).to have_attributes(src: "http://example.com/images/productivity.png")
         | 
| 69 136 | 
             
                    end
         | 
| 70 137 |  | 
| 71 | 
            -
                    it "assigns the updated_at attribute" do
         | 
| 72 | 
            -
                      subject
         | 
| 73 | 
            -
             | 
| 74 | 
            -
                      expect(action.model).to have_attributes(updated_at: a_kind_of(Time))
         | 
| 75 | 
            -
                    end
         | 
| 76 | 
            -
             | 
| 77 138 | 
             
                    it "assigns the active_photographer attribute" do
         | 
| 78 139 | 
             
                      subject
         | 
| 79 140 |  | 
| @@ -92,21 +153,10 @@ RSpec.describe JSONAPI::Realizer::Action::Create do | |
| 92 153 | 
             
                    include_examples "api"
         | 
| 93 154 |  | 
| 94 155 | 
             
                    it "creates the new record" do
         | 
| 95 | 
            -
                      expect  | 
| 96 | 
            -
                         | 
| 97 | 
            -
             | 
| 98 | 
            -
                         | 
| 99 | 
            -
                      }.from(
         | 
| 100 | 
            -
                        {}
         | 
| 101 | 
            -
                      ).to(
         | 
| 102 | 
            -
                        {
         | 
| 103 | 
            -
                          "550e8400-e29b-41d4-a716-446655440000" => hash_including(
         | 
| 104 | 
            -
                            id: "550e8400-e29b-41d4-a716-446655440000",
         | 
| 105 | 
            -
                            title: "Ember Hamster",
         | 
| 106 | 
            -
                            alt_text: "A hamster logo.",
         | 
| 107 | 
            -
                            src: "http://example.com/images/productivity.png"
         | 
| 108 | 
            -
                          )
         | 
| 109 | 
            -
                        }
         | 
| 156 | 
            +
                      expect(subject.model).to have_attributes(
         | 
| 157 | 
            +
                        title: "Ember Hamster",
         | 
| 158 | 
            +
                        alt_text: "A hamster logo.",
         | 
| 159 | 
            +
                        src: "http://example.com/images/productivity.png"
         | 
| 110 160 | 
             
                      )
         | 
| 111 161 | 
             
                    end
         | 
| 112 162 | 
             
                  end
         | 
| @@ -0,0 +1,27 @@ | |
| 1 | 
            +
            module JSONAPI
         | 
| 2 | 
            +
              module Realizer
         | 
| 3 | 
            +
                class Action
         | 
| 4 | 
            +
                  class Destroy < Action
         | 
| 5 | 
            +
                    attr_accessor :resource
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                    def initialize(payload:, headers:, scope: nil, type:)
         | 
| 8 | 
            +
                      @type = type
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                      super(payload: payload, headers: headers, scope: scope)
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                      @resource = resource_class.new(adapter.find_via_call(relation, id))
         | 
| 13 | 
            +
                    end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                    def model
         | 
| 16 | 
            +
                      resource.model
         | 
| 17 | 
            +
                    end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                    private def id
         | 
| 20 | 
            +
                      return data.fetch("id", nil) if data
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                      payload.fetch("id", nil)
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
            end
         | 
| @@ -0,0 +1,81 @@ | |
| 1 | 
            +
            require "spec_helper"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            RSpec.describe JSONAPI::Realizer::Action::Destroy do
         | 
| 4 | 
            +
              let(:action) { described_class.new(payload: payload, headers: headers, type: :photos) }
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              describe "#model" do
         | 
| 7 | 
            +
                subject { action.model }
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                context "with no top-level data and good content-type header no accept headers" do
         | 
| 10 | 
            +
                  let(:payload) do
         | 
| 11 | 
            +
                    {}
         | 
| 12 | 
            +
                  end
         | 
| 13 | 
            +
                  let(:headers) do
         | 
| 14 | 
            +
                    {
         | 
| 15 | 
            +
                      "Content-Type" => "application/vnd.api+json",
         | 
| 16 | 
            +
                    }
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  it "raises an exception" do
         | 
| 20 | 
            +
                    expect {subject}.to raise_exception(JSONAPI::Realizer::Error::MissingAcceptHeader)
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                context "with no top-level data and good content-type header and wrong accept header" do
         | 
| 25 | 
            +
                  let(:payload) do
         | 
| 26 | 
            +
                    {}
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
                  let(:headers) do
         | 
| 29 | 
            +
                    {
         | 
| 30 | 
            +
                      "Content-Type" => "application/vnd.api+json",
         | 
| 31 | 
            +
                      "Accept" => "application/json"
         | 
| 32 | 
            +
                    }
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  it "raises an exception" do
         | 
| 36 | 
            +
                    expect {subject}.to raise_exception(JSONAPI::Realizer::Error::InvalidAcceptHeader)
         | 
| 37 | 
            +
                  end
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                context "with a good payload and good headers" do
         | 
| 41 | 
            +
                  let(:payload) do
         | 
| 42 | 
            +
                    {
         | 
| 43 | 
            +
                      "id" => "d09ae4c6-0fc3-4c42-8fe8-6029530c3bed"
         | 
| 44 | 
            +
                    }
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
                  let(:headers) do
         | 
| 47 | 
            +
                    {
         | 
| 48 | 
            +
                      "Content-Type" => "application/vnd.api+json",
         | 
| 49 | 
            +
                      "Accept" => "application/vnd.api+json"
         | 
| 50 | 
            +
                    }
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                  shared_examples "api" do
         | 
| 54 | 
            +
                    it "returns a photo model" do
         | 
| 55 | 
            +
                      expect(subject).to be_a_kind_of(Photo)
         | 
| 56 | 
            +
                    end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                    it "returns the photos attributes" do
         | 
| 59 | 
            +
                      expect(subject).to have_attributes(title: "Ember Fox", src: "http://example.com/images/productivity-2.png")
         | 
| 60 | 
            +
                    end
         | 
| 61 | 
            +
                  end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                  context "in a memory store", memory: true do
         | 
| 64 | 
            +
                    before do
         | 
| 65 | 
            +
                      Photo::STORE["550e8400-e29b-41d4-a716-446655440000"] = {
         | 
| 66 | 
            +
                        id: "550e8400-e29b-41d4-a716-446655440000",
         | 
| 67 | 
            +
                        title: "Ember Hamster",
         | 
| 68 | 
            +
                        src: "http://example.com/images/productivity.png"
         | 
| 69 | 
            +
                      }
         | 
| 70 | 
            +
                      Photo::STORE["d09ae4c6-0fc3-4c42-8fe8-6029530c3bed"] = {
         | 
| 71 | 
            +
                        id: "d09ae4c6-0fc3-4c42-8fe8-6029530c3bed",
         | 
| 72 | 
            +
                        title: "Ember Fox",
         | 
| 73 | 
            +
                        src: "http://example.com/images/productivity-2.png"
         | 
| 74 | 
            +
                      }
         | 
| 75 | 
            +
                    end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                    include_examples "api"
         | 
| 78 | 
            +
                  end
         | 
| 79 | 
            +
                end
         | 
| 80 | 
            +
              end
         | 
| 81 | 
            +
            end
         | 
| @@ -4,12 +4,10 @@ module JSONAPI | |
| 4 4 | 
             
                  class Index < Action
         | 
| 5 5 | 
             
                    attr_accessor :resources
         | 
| 6 6 |  | 
| 7 | 
            -
                    def initialize(payload:, headers:, type:)
         | 
| 8 | 
            -
                      @payload = payload
         | 
| 9 | 
            -
                      @headers = headers
         | 
| 7 | 
            +
                    def initialize(payload:, headers:, scope: nil, type:)
         | 
| 10 8 | 
             
                      @type = type
         | 
| 11 9 |  | 
| 12 | 
            -
                      super(payload: payload, headers: headers)
         | 
| 10 | 
            +
                      super(payload: payload, headers: headers, scope: scope)
         | 
| 13 11 |  | 
| 14 12 | 
             
                      @resources = adapter.find_many_via_call(relation).map(&resource_class.method(:new))
         | 
| 15 13 | 
             
                    end
         | 
| @@ -6,9 +6,36 @@ RSpec.describe JSONAPI::Realizer::Action::Index do | |
| 6 6 | 
             
              describe "#models" do
         | 
| 7 7 | 
             
                subject { action.models }
         | 
| 8 8 |  | 
| 9 | 
            -
                context "with no top-level data and good headers"
         | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 9 | 
            +
                context "with no top-level data and good content-type header no accept headers" do
         | 
| 10 | 
            +
                  let(:payload) do
         | 
| 11 | 
            +
                    {}
         | 
| 12 | 
            +
                  end
         | 
| 13 | 
            +
                  let(:headers) do
         | 
| 14 | 
            +
                    {
         | 
| 15 | 
            +
                      "Content-Type" => "application/vnd.api+json",
         | 
| 16 | 
            +
                    }
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  it "raises an exception" do
         | 
| 20 | 
            +
                    expect {subject}.to raise_exception(JSONAPI::Realizer::Error::MissingAcceptHeader)
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                context "with no top-level data and good content-type header and wrong accept header" do
         | 
| 25 | 
            +
                  let(:payload) do
         | 
| 26 | 
            +
                    {}
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
                  let(:headers) do
         | 
| 29 | 
            +
                    {
         | 
| 30 | 
            +
                      "Content-Type" => "application/vnd.api+json",
         | 
| 31 | 
            +
                      "Accept" => "application/json"
         | 
| 32 | 
            +
                    }
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  it "raises an exception" do
         | 
| 36 | 
            +
                    expect {subject}.to raise_exception(JSONAPI::Realizer::Error::InvalidAcceptHeader)
         | 
| 37 | 
            +
                  end
         | 
| 38 | 
            +
                end
         | 
| 12 39 |  | 
| 13 40 | 
             
                context "with a good payload and good headers" do
         | 
| 14 41 | 
             
                  let(:payload) do
         | 
| @@ -2,15 +2,12 @@ module JSONAPI | |
| 2 2 | 
             
              module Realizer
         | 
| 3 3 | 
             
                class Action
         | 
| 4 4 | 
             
                  class Show < Action
         | 
| 5 | 
            -
             | 
| 6 5 | 
             
                    attr_accessor :resource
         | 
| 7 6 |  | 
| 8 | 
            -
                    def initialize(payload:, headers:, type:)
         | 
| 9 | 
            -
                      @payload = payload
         | 
| 10 | 
            -
                      @headers = headers
         | 
| 7 | 
            +
                    def initialize(payload:, headers:, scope: nil, type:)
         | 
| 11 8 | 
             
                      @type = type
         | 
| 12 9 |  | 
| 13 | 
            -
                      super(payload: payload, headers: headers)
         | 
| 10 | 
            +
                      super(payload: payload, headers: headers, scope: scope)
         | 
| 14 11 |  | 
| 15 12 | 
             
                      @resource = resource_class.new(adapter.find_via_call(relation, id))
         | 
| 16 13 | 
             
                    end
         | 
| @@ -6,9 +6,36 @@ RSpec.describe JSONAPI::Realizer::Action::Show do | |
| 6 6 | 
             
              describe "#model" do
         | 
| 7 7 | 
             
                subject { action.model }
         | 
| 8 8 |  | 
| 9 | 
            -
                context "with no top-level data and good headers"
         | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 9 | 
            +
                context "with no top-level data and good content-type header no accept headers" do
         | 
| 10 | 
            +
                  let(:payload) do
         | 
| 11 | 
            +
                    {}
         | 
| 12 | 
            +
                  end
         | 
| 13 | 
            +
                  let(:headers) do
         | 
| 14 | 
            +
                    {
         | 
| 15 | 
            +
                      "Content-Type" => "application/vnd.api+json",
         | 
| 16 | 
            +
                    }
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  it "raises an exception" do
         | 
| 20 | 
            +
                    expect {subject}.to raise_exception(JSONAPI::Realizer::Error::MissingAcceptHeader)
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                context "with no top-level data and good content-type header and wrong accept header" do
         | 
| 25 | 
            +
                  let(:payload) do
         | 
| 26 | 
            +
                    {}
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
                  let(:headers) do
         | 
| 29 | 
            +
                    {
         | 
| 30 | 
            +
                      "Content-Type" => "application/vnd.api+json",
         | 
| 31 | 
            +
                      "Accept" => "application/json"
         | 
| 32 | 
            +
                    }
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  it "raises an exception" do
         | 
| 36 | 
            +
                    expect {subject}.to raise_exception(JSONAPI::Realizer::Error::InvalidAcceptHeader)
         | 
| 37 | 
            +
                  end
         | 
| 38 | 
            +
                end
         | 
| 12 39 |  | 
| 13 40 | 
             
                context "with a good payload and good headers" do
         | 
| 14 41 | 
             
                  let(:payload) do
         | 
| @@ -4,26 +4,22 @@ module JSONAPI | |
| 4 4 | 
             
                  class Update < Action
         | 
| 5 5 | 
             
                    attr_accessor :resource
         | 
| 6 6 |  | 
| 7 | 
            -
                    def initialize(payload:, headers:)
         | 
| 8 | 
            -
                      @payload = payload
         | 
| 9 | 
            -
                      @headers = headers
         | 
| 10 | 
            -
             | 
| 7 | 
            +
                    def initialize(payload:, headers:, scope: nil)
         | 
| 11 8 | 
             
                      raise Error::MissingContentTypeHeader unless headers.key?("Content-Type")
         | 
| 12 | 
            -
                      raise Error::InvalidContentTypeHeader unless headers.fetch("Content-Type") ==  | 
| 9 | 
            +
                      raise Error::InvalidContentTypeHeader unless headers.fetch("Content-Type") == JSONAPI::MEDIA_TYPE
         | 
| 13 10 |  | 
| 14 | 
            -
                      super(payload: payload, headers: headers)
         | 
| 11 | 
            +
                      super(payload: payload, headers: headers, scope: scope)
         | 
| 15 12 |  | 
| 16 13 | 
             
                      @resource = resource_class.new(adapter.find_via_call(relation, id))
         | 
| 17 14 |  | 
| 18 | 
            -
                      raise Error::MissingRootProperty unless payload.key?("data") || payload.key?("errors") || payload.key?("meta")
         | 
| 19 | 
            -
                      raise Error::MissingTypeResourceProperty if payload.key?("data") && data.kind_of?(Hash) && !data.key?("type")
         | 
| 20 | 
            -
                      raise Error::MissingTypeResourceProperty if payload.key?("data") && data.kind_of?(Array) && !data.all? {|resource| resource.key?("type")}
         | 
| 15 | 
            +
                      raise Error::MissingRootProperty unless @payload.key?("data") || @payload.key?("errors") || @payload.key?("meta")
         | 
| 16 | 
            +
                      raise Error::MissingTypeResourceProperty if @payload.key?("data") && data.kind_of?(Hash) && !data.key?("type")
         | 
| 17 | 
            +
                      raise Error::MissingTypeResourceProperty if @payload.key?("data") && data.kind_of?(Array) && !data.all? {|resource| resource.key?("type")}
         | 
| 21 18 | 
             
                    end
         | 
| 22 19 |  | 
| 23 20 | 
             
                    def call
         | 
| 24 21 | 
             
                      adapter.assign_attributes_via_call(resource.model, attributes)
         | 
| 25 22 | 
             
                      adapter.assign_relationships_via_call(resource.model, relationships)
         | 
| 26 | 
            -
                      adapter.update_via_call(resource.model)
         | 
| 27 23 | 
             
                    end
         | 
| 28 24 |  | 
| 29 25 | 
             
                    def model
         | 
| @@ -4,7 +4,7 @@ RSpec.describe JSONAPI::Realizer::Action::Update do | |
| 4 4 | 
             
              let(:action) { described_class.new(payload: payload, headers: headers) }
         | 
| 5 5 |  | 
| 6 6 | 
             
              describe "#call" do
         | 
| 7 | 
            -
                subject { action.call }
         | 
| 7 | 
            +
                subject { action.tap(&:call) }
         | 
| 8 8 |  | 
| 9 9 | 
             
                context "with no top-level data and no content-type header no accept headers" do
         | 
| 10 10 | 
             
                  let(:payload) do
         | 
| @@ -134,12 +134,6 @@ RSpec.describe JSONAPI::Realizer::Action::Update do | |
| 134 134 | 
             
                      expect(action.model).to have_attributes(src: "http://example.com/images/productivity-2.png")
         | 
| 135 135 | 
             
                    end
         | 
| 136 136 |  | 
| 137 | 
            -
                    it "assigns the updated_at attribute" do
         | 
| 138 | 
            -
                      subject
         | 
| 139 | 
            -
             | 
| 140 | 
            -
                      expect(action.model).to have_attributes(updated_at: a_kind_of(Time))
         | 
| 141 | 
            -
                    end
         | 
| 142 | 
            -
             | 
| 143 137 | 
             
                    it "assigns the active_photographer attribute" do
         | 
| 144 138 | 
             
                      subject
         | 
| 145 139 |  | 
| @@ -163,27 +157,11 @@ RSpec.describe JSONAPI::Realizer::Action::Update do | |
| 163 157 | 
             
                    include_examples "api"
         | 
| 164 158 |  | 
| 165 159 | 
             
                    it "updates the record" do
         | 
| 166 | 
            -
                      expect  | 
| 167 | 
            -
                         | 
| 168 | 
            -
             | 
| 169 | 
            -
                         | 
| 170 | 
            -
             | 
| 171 | 
            -
                        {
         | 
| 172 | 
            -
                          "550e8400-e29b-41d4-a716-446655440000" => hash_including(
         | 
| 173 | 
            -
                            id: "550e8400-e29b-41d4-a716-446655440000",
         | 
| 174 | 
            -
                            title: "Ember Hamster",
         | 
| 175 | 
            -
                            src: "http://example.com/images/productivity.png"
         | 
| 176 | 
            -
                          )
         | 
| 177 | 
            -
                        }
         | 
| 178 | 
            -
                      ).to(
         | 
| 179 | 
            -
                        {
         | 
| 180 | 
            -
                          "550e8400-e29b-41d4-a716-446655440000" => hash_including(
         | 
| 181 | 
            -
                            id: "550e8400-e29b-41d4-a716-446655440000",
         | 
| 182 | 
            -
                            title: "Ember Hamster 2",
         | 
| 183 | 
            -
                            alt_text: "A hamster logo.",
         | 
| 184 | 
            -
                            src: "http://example.com/images/productivity-2.png"
         | 
| 185 | 
            -
                          )
         | 
| 186 | 
            -
                        }
         | 
| 160 | 
            +
                      expect(subject.model).to have_attributes(
         | 
| 161 | 
            +
                        id: "550e8400-e29b-41d4-a716-446655440000",
         | 
| 162 | 
            +
                        title: "Ember Hamster 2",
         | 
| 163 | 
            +
                        alt_text: "A hamster logo.",
         | 
| 164 | 
            +
                        src: "http://example.com/images/productivity-2.png"
         | 
| 187 165 | 
             
                      )
         | 
| 188 166 | 
             
                    end
         | 
| 189 167 | 
             
                  end
         | 
| @@ -5,62 +5,66 @@ module JSONAPI | |
| 5 5 | 
             
                  require_relative "action/update"
         | 
| 6 6 | 
             
                  require_relative "action/show"
         | 
| 7 7 | 
             
                  require_relative "action/index"
         | 
| 8 | 
            +
                  require_relative "action/destroy"
         | 
| 8 9 |  | 
| 9 10 | 
             
                  attr_reader :payload
         | 
| 10 11 | 
             
                  attr_reader :headers
         | 
| 11 12 |  | 
| 12 | 
            -
                  def initialize(payload:, headers:)
         | 
| 13 | 
            -
                     | 
| 14 | 
            -
                     | 
| 15 | 
            -
                     | 
| 16 | 
            -
             | 
| 17 | 
            -
                    raise Error:: | 
| 13 | 
            +
                  def initialize(payload:, headers:, scope: nil)
         | 
| 14 | 
            +
                    @scope = scope
         | 
| 15 | 
            +
                    @headers = headers
         | 
| 16 | 
            +
                    @payload = payload
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                    raise Error::MissingAcceptHeader unless @headers.key?("Accept")
         | 
| 19 | 
            +
                    raise Error::InvalidAcceptHeader unless @headers.fetch("Accept") == JSONAPI::MEDIA_TYPE
         | 
| 20 | 
            +
                    raise Error::IncludeWithoutDataProperty if @payload.key?("include") && !@payload.key?("data")
         | 
| 21 | 
            +
                    raise Error::MalformedDataRootProperty if @payload.key?("data") && !(data.kind_of?(Array) || data.kind_of?(Hash) || data.nil?)
         | 
| 18 22 | 
             
                  end
         | 
| 19 23 |  | 
| 20 24 | 
             
                  def call; end
         | 
| 21 25 |  | 
| 22 26 | 
             
                  private def model_class
         | 
| 23 | 
            -
                    resource_class.model_class
         | 
| 27 | 
            +
                    resource_class.model_class if resource_class
         | 
| 24 28 | 
             
                  end
         | 
| 25 29 |  | 
| 26 30 | 
             
                  private def resource_class
         | 
| 27 | 
            -
                    configuration.resource_class
         | 
| 31 | 
            +
                    configuration.resource_class if configuration
         | 
| 28 32 | 
             
                  end
         | 
| 29 33 |  | 
| 30 34 | 
             
                  private def adapter
         | 
| 31 | 
            -
                    configuration.adapter
         | 
| 35 | 
            +
                    configuration.adapter if configuration
         | 
| 32 36 | 
             
                  end
         | 
| 33 37 |  | 
| 34 | 
            -
                  private def relation_after_inclusion( | 
| 38 | 
            +
                  private def relation_after_inclusion(subrelation)
         | 
| 35 39 | 
             
                    if includes.any?
         | 
| 36 | 
            -
                      resource_class.include_via_call( | 
| 40 | 
            +
                      resource_class.include_via_call(subrelation, includes)
         | 
| 37 41 | 
             
                    else
         | 
| 38 | 
            -
                       | 
| 42 | 
            +
                      subrelation
         | 
| 39 43 | 
             
                    end
         | 
| 40 44 | 
             
                  end
         | 
| 41 45 |  | 
| 42 | 
            -
                  private def relation_after_fields( | 
| 46 | 
            +
                  private def relation_after_fields(subrelation)
         | 
| 43 47 | 
             
                    if fields.any?
         | 
| 44 | 
            -
                      resource_class.sparse_fields_call( | 
| 48 | 
            +
                      resource_class.sparse_fields_call(subrelation, fields)
         | 
| 45 49 | 
             
                    else
         | 
| 46 | 
            -
                       | 
| 50 | 
            +
                      subrelation
         | 
| 47 51 | 
             
                    end
         | 
| 48 52 | 
             
                  end
         | 
| 49 53 |  | 
| 50 54 | 
             
                  private def relation
         | 
| 51 55 | 
             
                    relation_after_fields(
         | 
| 52 56 | 
             
                      relation_after_inclusion(
         | 
| 53 | 
            -
                        model_class
         | 
| 57 | 
            +
                        @scope || model_class
         | 
| 54 58 | 
             
                      )
         | 
| 55 59 | 
             
                    )
         | 
| 56 60 | 
             
                  end
         | 
| 57 61 |  | 
| 58 62 | 
             
                  private def data
         | 
| 59 | 
            -
                    payload.fetch("data")
         | 
| 63 | 
            +
                    payload.fetch("data", nil)
         | 
| 60 64 | 
             
                  end
         | 
| 61 65 |  | 
| 62 66 | 
             
                  private def type
         | 
| 63 | 
            -
                    data["type"].to_s.dasherize if data
         | 
| 67 | 
            +
                    (@type || data["type"]).to_s.dasherize if @type || data
         | 
| 64 68 | 
             
                  end
         | 
| 65 69 |  | 
| 66 70 | 
             
                  private def attributes
         | 
| @@ -88,6 +92,7 @@ module JSONAPI | |
| 88 92 | 
             
                  end
         | 
| 89 93 |  | 
| 90 94 | 
             
                  def includes
         | 
| 95 | 
            +
                    return [] unless payload.present?
         | 
| 91 96 | 
             
                    return [] unless payload.key?("include")
         | 
| 92 97 |  | 
| 93 98 | 
             
                    payload.
         | 
| @@ -111,6 +116,7 @@ module JSONAPI | |
| 111 116 | 
             
                  end
         | 
| 112 117 |  | 
| 113 118 | 
             
                  def fields
         | 
| 119 | 
            +
                    return [] unless payload.present?
         | 
| 114 120 | 
             
                    return [] unless payload.key?("fields")
         | 
| 115 121 |  | 
| 116 122 | 
             
                    payload.
         | 
| @@ -138,7 +144,7 @@ module JSONAPI | |
| 138 144 | 
             
                  end
         | 
| 139 145 |  | 
| 140 146 | 
             
                  private def configuration
         | 
| 141 | 
            -
                    JSONAPI::Realizer.type_mapping.fetch(type)
         | 
| 147 | 
            +
                    JSONAPI::Realizer.type_mapping.fetch(type) if type
         | 
| 142 148 | 
             
                  end
         | 
| 143 149 | 
             
                end
         | 
| 144 150 | 
             
              end
         | 
| @@ -1,13 +1,13 @@ | |
| 1 1 | 
             
            require "spec_helper"
         | 
| 2 2 |  | 
| 3 3 | 
             
            RSpec.describe JSONAPI::Realizer::Action do
         | 
| 4 | 
            +
              let(:headers) do
         | 
| 5 | 
            +
                {
         | 
| 6 | 
            +
                  "Accept" => JSONAPI::MEDIA_TYPE
         | 
| 7 | 
            +
                }
         | 
| 8 | 
            +
              end
         | 
| 4 9 | 
             
              let(:action) do
         | 
| 5 | 
            -
                 | 
| 6 | 
            -
                  def initialize(payload:, type:)
         | 
| 7 | 
            -
                    @payload = payload
         | 
| 8 | 
            -
                    @type = type
         | 
| 9 | 
            -
                  end
         | 
| 10 | 
            -
                end.new(payload: payload, type: :photos)
         | 
| 10 | 
            +
                ExampleAction.new(payload: payload, headers: headers, type: :photos)
         | 
| 11 11 | 
             
              end
         | 
| 12 12 |  | 
| 13 13 | 
             
              describe "#includes" do
         | 
| @@ -16,6 +16,7 @@ RSpec.describe JSONAPI::Realizer::Action do | |
| 16 16 | 
             
                context "with a two good and one bad" do
         | 
| 17 17 | 
             
                  let(:payload) do
         | 
| 18 18 | 
             
                    {
         | 
| 19 | 
            +
                      "data" => nil,
         | 
| 19 20 | 
             
                      "include" => "active_photographer,active_photographer.posts.comments,active_photographer.posts"
         | 
| 20 21 | 
             
                    }
         | 
| 21 22 | 
             
                  end
         | 
| @@ -32,6 +33,7 @@ RSpec.describe JSONAPI::Realizer::Action do | |
| 32 33 | 
             
                context "with a two good and one bad" do
         | 
| 33 34 | 
             
                  let(:payload) do
         | 
| 34 35 | 
             
                    {
         | 
| 36 | 
            +
                      "data" => nil,
         | 
| 35 37 | 
             
                      "fields" => "title,active_photographer.posts.comments.body,active_photographer.name"
         | 
| 36 38 | 
             
                    }
         | 
| 37 39 | 
             
                  end
         | 
| @@ -25,21 +25,6 @@ module JSONAPI | |
| 25 25 | 
             
                    include_via do |model_class, includes|
         | 
| 26 26 | 
             
                      model_class
         | 
| 27 27 | 
             
                    end
         | 
| 28 | 
            -
             | 
| 29 | 
            -
                    create_via do |model|
         | 
| 30 | 
            -
                      model.assign_attributes(id: model.id || SecureRandom.uuid)
         | 
| 31 | 
            -
                      model.assign_attributes(updated_at: Time.now)
         | 
| 32 | 
            -
                      model.class.const_get("STORE")[model.id] = model.class.const_get("ATTRIBUTES").inject({}) do |hash, key|
         | 
| 33 | 
            -
                        hash.merge({ key => model.public_send(key) })
         | 
| 34 | 
            -
                      end
         | 
| 35 | 
            -
                    end
         | 
| 36 | 
            -
             | 
| 37 | 
            -
                    update_via do |model|
         | 
| 38 | 
            -
                      model.assign_attributes(updated_at: Time.now)
         | 
| 39 | 
            -
                      model.class.const_get("STORE")[model.id] = model.class.const_get("ATTRIBUTES").inject({}) do |hash, key|
         | 
| 40 | 
            -
                        hash.merge({ key => model.public_send(key) })
         | 
| 41 | 
            -
                      end
         | 
| 42 | 
            -
                    end
         | 
| 43 28 | 
             
                  end
         | 
| 44 29 | 
             
                end
         | 
| 45 30 | 
             
              end
         | 
| @@ -20,8 +20,6 @@ module JSONAPI | |
| 20 20 | 
             
                    raise ArgumentError, "need to provide a Adapter.find_many_via_call interface" unless instance_variable_defined?(:@find_many_via_call)
         | 
| 21 21 | 
             
                    raise ArgumentError, "need to provide a Adapter.assign_attributes_via interface" unless instance_variable_defined?(:@assign_attributes_via_call)
         | 
| 22 22 | 
             
                    raise ArgumentError, "need to provide a Adapter.assign_relationships_via interface" unless instance_variable_defined?(:@assign_relationships_via_call)
         | 
| 23 | 
            -
                    raise ArgumentError, "need to provide a Adapter.create_via interface" unless instance_variable_defined?(:@create_via_call)
         | 
| 24 | 
            -
                    raise ArgumentError, "need to provide a Adapter.update_via interface" unless instance_variable_defined?(:@update_via_call)
         | 
| 25 23 | 
             
                    raise ArgumentError, "need to provide a Adapter.sparse_fields interface" unless instance_variable_defined?(:@sparse_fields_call)
         | 
| 26 24 | 
             
                    raise ArgumentError, "need to provide a Adapter.include_via interface" unless instance_variable_defined?(:@include_via_call)
         | 
| 27 25 | 
             
                  end
         | 
| @@ -34,14 +32,6 @@ module JSONAPI | |
| 34 32 | 
             
                    @find_many_via_call = callback
         | 
| 35 33 | 
             
                  end
         | 
| 36 34 |  | 
| 37 | 
            -
                  def create_via(&callback)
         | 
| 38 | 
            -
                    @create_via_call = callback
         | 
| 39 | 
            -
                  end
         | 
| 40 | 
            -
             | 
| 41 | 
            -
                  def update_via(&callback)
         | 
| 42 | 
            -
                    @update_via_call = callback
         | 
| 43 | 
            -
                  end
         | 
| 44 | 
            -
             | 
| 45 35 | 
             
                  def assign_attributes_via(&callback)
         | 
| 46 36 | 
             
                    @assign_attributes_via_call = callback
         | 
| 47 37 | 
             
                  end
         | 
| @@ -66,14 +56,6 @@ module JSONAPI | |
| 66 56 | 
             
                    @find_many_via_call.call(model_class)
         | 
| 67 57 | 
             
                  end
         | 
| 68 58 |  | 
| 69 | 
            -
                  def create_via_call(model)
         | 
| 70 | 
            -
                    @create_via_call.call(model)
         | 
| 71 | 
            -
                  end
         | 
| 72 | 
            -
             | 
| 73 | 
            -
                  def update_via_call(model)
         | 
| 74 | 
            -
                    @update_via_call.call(model)
         | 
| 75 | 
            -
                  end
         | 
| 76 | 
            -
             | 
| 77 59 | 
             
                  def assign_attributes_via_call(model, attributes)
         | 
| 78 60 | 
             
                    @assign_attributes_via_call.call(model, attributes)
         | 
| 79 61 | 
             
                  end
         | 
| @@ -26,13 +26,5 @@ RSpec.describe JSONAPI::Realizer::Adapter do | |
| 26 26 | 
             
                context "when the assign_attributes_via interface isn't defined" do
         | 
| 27 27 |  | 
| 28 28 | 
             
                end
         | 
| 29 | 
            -
             | 
| 30 | 
            -
                context "when the create_via interface isn't defined" do
         | 
| 31 | 
            -
             | 
| 32 | 
            -
                end
         | 
| 33 | 
            -
             | 
| 34 | 
            -
                context "when the update_via interface isn't defined" do
         | 
| 35 | 
            -
             | 
| 36 | 
            -
                end
         | 
| 37 29 | 
             
              end
         | 
| 38 30 | 
             
            end
         | 
    
        data/lib/jsonapi/realizer.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: jsonapi-realizer
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version:  | 
| 4 | 
            +
              version: 4.0.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Kurtis Rainbolt-Greene
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2018-03- | 
| 11 | 
            +
            date: 2018-03-25 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: bundler
         | 
| @@ -136,6 +136,8 @@ files: | |
| 136 136 | 
             
            - lib/jsonapi/realizer/action.rb
         | 
| 137 137 | 
             
            - lib/jsonapi/realizer/action/create.rb
         | 
| 138 138 | 
             
            - lib/jsonapi/realizer/action/create_spec.rb
         | 
| 139 | 
            +
            - lib/jsonapi/realizer/action/destroy.rb
         | 
| 140 | 
            +
            - lib/jsonapi/realizer/action/destroy_spec.rb
         | 
| 139 141 | 
             
            - lib/jsonapi/realizer/action/index.rb
         | 
| 140 142 | 
             
            - lib/jsonapi/realizer/action/index_spec.rb
         | 
| 141 143 | 
             
            - lib/jsonapi/realizer/action/show.rb
         | 
| @@ -156,7 +158,6 @@ files: | |
| 156 158 | 
             
            - lib/jsonapi/realizer/error/missing_content_type_header.rb
         | 
| 157 159 | 
             
            - lib/jsonapi/realizer/error/missing_root_property.rb
         | 
| 158 160 | 
             
            - lib/jsonapi/realizer/error/missing_type_resource_property.rb
         | 
| 159 | 
            -
            - lib/jsonapi/realizer/error/too_many_root_properties.rb
         | 
| 160 161 | 
             
            - lib/jsonapi/realizer/resource.rb
         | 
| 161 162 | 
             
            - lib/jsonapi/realizer/version.rb
         | 
| 162 163 | 
             
            - lib/jsonapi/realizer/version_spec.rb
         | 
| @@ -181,7 +182,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 181 182 | 
             
                  version: '0'
         | 
| 182 183 | 
             
            requirements: []
         | 
| 183 184 | 
             
            rubyforge_project: 
         | 
| 184 | 
            -
            rubygems_version: 2.7. | 
| 185 | 
            +
            rubygems_version: 2.7.6
         | 
| 185 186 | 
             
            signing_key: 
         | 
| 186 187 | 
             
            specification_version: 4
         | 
| 187 188 | 
             
            summary: A way to take json:api requests and turn them into models
         |