jsonapi-realizer 1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f3e9f32f5798910d492d81a0564ff99337b65577d7f0fff93cc1b627c53e0bd2
4
+ data.tar.gz: 754cf56ffe68f405a1b68ee3d2ebb2da4d8b89146f6048e6e5c4d9755b72ff93
5
+ SHA512:
6
+ metadata.gz: '076844edcdb11676eb825d8707c331fc00736cf5c31e2b345fb134cb28363315ee317d046830aa4d654741560a66ad5a2caef71cd224b12c372b427d9517cf26'
7
+ data.tar.gz: 6216f9f0c53cf4b27f25f4c90e768092525e477de0156d9fbbdd09d4e952513a3f73b8247b803d9325a3883f6f2d07a1a8b846a2986c6c9de839210c6de37cab
data/README.md ADDED
@@ -0,0 +1,169 @@
1
+ # jsonapi-realizer
2
+
3
+ - [![Build](http://img.shields.io/travis-ci/krainboltgreene/jsonapi-realizer.svg?style=flat-square)](https://travis-ci.org/krainboltgreene/jsonapi-realizer)
4
+ - [![Downloads](http://img.shields.io/gem/dtv/jsonapi-realizer.svg?style=flat-square)](https://rubygems.org/gems/jsonapi-realizer)
5
+ - [![Version](http://img.shields.io/gem/v/jsonapi-realizer.svg?style=flat-square)](https://rubygems.org/gems/jsonapi-realizer)
6
+
7
+
8
+ This library handles incoming [json:api](https://www.jsonapi.org) payloads and turns them, via an adapter system, into data models for your business logic.
9
+
10
+ A successful JSON:API request can be annotated as:
11
+
12
+ ```
13
+ JSONAPIRequest -> (PersistanceAdapter -> JSONAPIRequest -> (Record | Array<Record>)) -> JSONAPIResponse
14
+ ```
15
+
16
+ The `jsonapi-serializers` library provides this shape:
17
+
18
+ ```
19
+ JSONAPIRequest -> (Record | Array<Record>) -> JSONAPIResponse
20
+ ```
21
+
22
+ But it leaves fetching/createing/updating/destroying the records up to you! This is where jsonapi-realizer comes into play, as it provides this shape:
23
+
24
+ ```
25
+ PersistanceAdapter -> JSONAPIRequest -> (Record | Array<Record>)
26
+ ```
27
+
28
+
29
+ ## Using
30
+
31
+ ``` ruby
32
+ class Photo < ApplicationRecord
33
+ belongs_to :photographer, class_name: "Profile"
34
+ end
35
+
36
+ class Profile < ApplicationRecord
37
+ has_many :photos
38
+ end
39
+
40
+ class PhotoRealizer
41
+ include JSONAPI::Realizer::Resource
42
+
43
+ adapter :active_record
44
+
45
+ represents :photos, class_name: "Photo"
46
+
47
+ has_one :photographer, as: :profiles
48
+
49
+ has :title
50
+ has :src
51
+ end
52
+
53
+ class ProfileRealizer
54
+ include JSONAPI::Realizer::Resource
55
+
56
+ adapter :active_record
57
+
58
+ represents :profiles, class_name: "Profile"
59
+
60
+ has_many :photos, as: :photos
61
+
62
+ has :name
63
+ end
64
+ ```
65
+
66
+ Once you've designed your resources, we just need to use them! In this example, we'll use controllers from Rails:
67
+
68
+ ``` ruby
69
+ class PhotosController < ApplicationController
70
+ def create
71
+ validate_parameters!
72
+ authenticate_session!
73
+
74
+ record = JSONAPI::Realizer.create(params, headers: request.headers)
75
+
76
+ ProcessPhotosService.new(record)
77
+
78
+ JSONAPI::Serializer.serialize(record)
79
+ end
80
+ end
81
+ ```
82
+
83
+ ### Adapters
84
+
85
+ There are two core adapters:
86
+
87
+ 0. `:active_record`, which assumes an ActiveRecord-like interface.
88
+ 0. `:memory`, which assumes a `STORE` Hash-like on the model class.
89
+
90
+ An adapter must provide the following interfaces:
91
+
92
+ 0. `find_via`, which tells the action how to find the model
93
+ 0. `write_attributes_via`, which tells the action how to write an individual property
94
+ 0. `save_via`, which tells the action how to save the model when it's done
95
+
96
+ You can also provide custom adapter interfaces:
97
+
98
+ ``` ruby
99
+ class PhotoRealizer
100
+ include JSONAPI::Realizer::Resource
101
+
102
+ adapter do
103
+ find_via do |model_class, id|
104
+ model_class.where { id == id or slug == id }.first
105
+ end
106
+
107
+ write_attributes_via do |model, attributes|
108
+ model.update_columns(attributes)
109
+ end
110
+
111
+ save_via do |model|
112
+ model.save!
113
+ Rails.cache.write(model.cache_key, model)
114
+ end
115
+ end
116
+
117
+ represents :photos, class_name: "Photo"
118
+
119
+ has_one :photographer, as: :profiles
120
+
121
+ has :title
122
+ has :src
123
+ end
124
+ ```
125
+
126
+ If you want, you can use both the regular adapters and some custom pieces:
127
+
128
+ ``` ruby
129
+ class PhotoRealizer
130
+ include JSONAPI::Realizer::Resource
131
+
132
+ adapter :active_record do
133
+ find_via do |model_class, id|
134
+ model_class.where { id == id or slug == id }.first
135
+ end
136
+ end
137
+
138
+ represents :photos, class_name: "Photo"
139
+
140
+ has_one :photographer, as: :profiles
141
+
142
+ has :title
143
+ has :src
144
+ end
145
+ ```
146
+
147
+ ## Installing
148
+
149
+ Add this line to your application's Gemfile:
150
+
151
+ gem "jsonapi-realizer", "1.0.0"
152
+
153
+ And then execute:
154
+
155
+ $ bundle
156
+
157
+ Or install it yourself with:
158
+
159
+ $ gem install jsonapi-realizer
160
+
161
+
162
+ ## Contributing
163
+
164
+ 1. Read the [Code of Conduct](/CONDUCT.md)
165
+ 2. Fork it
166
+ 3. Create your feature branch (`git checkout -b my-new-feature`)
167
+ 4. Commit your changes (`git commit -am 'Add some feature'`)
168
+ 5. Push to the branch (`git push origin my-new-feature`)
169
+ 6. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env rake
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ desc "Run all the tests in spec"
7
+ RSpec::Core::RakeTask.new(:spec) do |let|
8
+ let.pattern = "lib/**{,/*/**}/*_spec.rb"
9
+ end
10
+
11
+ desc "Default: run tests"
12
+ task default: :spec
@@ -0,0 +1,3 @@
1
+ module JSONAPI
2
+ require_relative "jsonapi/realizer"
3
+ end
@@ -0,0 +1,30 @@
1
+ require "ostruct"
2
+ require "active_support/concern"
3
+
4
+ module JSONAPI
5
+ module Realizer
6
+ require_relative "realizer/version"
7
+ require_relative "realizer/action"
8
+ require_relative "realizer/adapter"
9
+ require_relative "realizer/resource"
10
+
11
+ def self.register(resource_class, model_class, type)
12
+ @mapping ||= {}
13
+ @mapping[type] = OpenStruct.new({
14
+ model_class: model_class,
15
+ type: type,
16
+ resource_class: resource_class,
17
+ attributes: OpenStruct.new({}),
18
+ relationships: OpenStruct.new({})
19
+ })
20
+ end
21
+
22
+ def self.mapping
23
+ @mapping
24
+ end
25
+
26
+ def self.create(payload, headers:)
27
+ Create.new(payload: payload, headers: headers).call
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,40 @@
1
+ module JSONAPI
2
+ module Realizer
3
+ class Action
4
+ require_relative "action/create"
5
+ require_relative "action/update"
6
+
7
+ attr_reader :type
8
+ attr_reader :data
9
+ attr_reader :resource
10
+
11
+ def initialize(payload:, headers:)
12
+ raise NoMethodError, "must implement this function"
13
+ end
14
+
15
+ def call
16
+ raise NoMethodError, "must implement this function"
17
+ end
18
+
19
+ private def resource_class
20
+ JSONAPI::Realizer.mapping.fetch(type).resource_class
21
+ end
22
+
23
+ private def relationships
24
+ data.fetch("relationships", {})
25
+ end
26
+
27
+ private def id
28
+ data.fetch("id", nil)
29
+ end
30
+
31
+ private def type
32
+ data.fetch("type")
33
+ end
34
+
35
+ private def attributes
36
+ data.fetch("attributes", {})
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,21 @@
1
+ module JSONAPI
2
+ module Realizer
3
+ class Action
4
+ class Create < Action
5
+ def initialize(payload:, headers:)
6
+ @data = payload.fetch("data")
7
+ @resource = resource_class.new(resource_class.model_class.new)
8
+ end
9
+
10
+ def call
11
+ resource.model.tap do |model|
12
+ resource_class.write_attributes_via_call(model, {id: id}) if id
13
+ resource_class.write_attributes_via_call(model, attributes.select(&resource.method(:valid_attribute?)))
14
+ resource_class.write_attributes_via_call(model, relationships.select(&resource.method(:valid_relationship?)).transform_values(&resource.method(:as_relationship)))
15
+ resource_class.save_via_call(model)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,58 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe JSONAPI::Realizer::Action::Create do
4
+ let(:action) { described_class.new(payload: payload, headers: headers) }
5
+
6
+ describe "#call" do
7
+ subject { action.call }
8
+
9
+ context "with a good payload and good headers" do
10
+ let(:payload) do
11
+ {
12
+ "data" => {
13
+ "id" => "550e8400-e29b-41d4-a716-446655440000",
14
+ "type" => "photos",
15
+ "attributes" => {
16
+ "title" => "Ember Hamster",
17
+ "src" => "http://example.com/images/productivity.png"
18
+ },
19
+ "relationships" => {
20
+ "photographer" => {
21
+ "data" => { "type" => "people", "id" => "4b8a0af6-953d-4729-8b9a-1fa4eb18f3c9" }
22
+ }
23
+ }
24
+ }
25
+ }
26
+ end
27
+ let(:headers) do
28
+ {
29
+ "Content-Type" => "application/vnd.api+json",
30
+ "Accept" => "application/vnd.api+json"
31
+ }
32
+ end
33
+
34
+ before do
35
+ People::STORE["4b8a0af6-953d-4729-8b9a-1fa4eb18f3c9"] = {
36
+ id: "4b8a0af6-953d-4729-8b9a-1fa4eb18f3c9",
37
+ name: "Kurtis Rainbolt-Greene"
38
+ }
39
+ end
40
+
41
+ it "creates a model" do
42
+ expect(subject).to be_a_kind_of(Photo)
43
+ end
44
+
45
+ it "assigns the attributes" do
46
+ expect(subject).to have_attributes(title: "Ember Hamster", src: "http://example.com/images/productivity.png", updated_at: a_kind_of(Time))
47
+ end
48
+
49
+ it "relates the relationships" do
50
+ expect(subject).to have_attributes(photographer: a_kind_of(People))
51
+ end
52
+
53
+ it "stores the new record" do
54
+ expect {subject}.to change {Photo::STORE}.from({}).to({"550e8400-e29b-41d4-a716-446655440000" => hash_including(id: "550e8400-e29b-41d4-a716-446655440000", title: "Ember Hamster", src: "http://example.com/images/productivity.png")})
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,25 @@
1
+ module JSONAPI
2
+ module Realizer
3
+ class Action
4
+ class Update < Action
5
+ def initialize(payload:, headers:)
6
+ @data = payload.fetch("data")
7
+ @resource = resource_class.new(
8
+ resource_class.find_via_call(
9
+ resource_class.model_class,
10
+ id
11
+ )
12
+ )
13
+ end
14
+
15
+ def call
16
+ @resource.model.tap do |model|
17
+ resource_class.write_attributes_via_call(model, attributes.select(&resource.method(:valid_attribute?)))
18
+ resource_class.write_attributes_via_call(model, relationships.select(&resource.method(:valid_relationship?)).transform_values(&resource.method(:as_relationship)))
19
+ resource_class.save_via_call(model)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,63 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe JSONAPI::Realizer::Action::Update do
4
+ let(:action) { described_class.new(payload: payload, headers: headers) }
5
+
6
+ describe "#call" do
7
+ subject { action.call }
8
+
9
+ context "with a good payload and good headers" do
10
+ let(:payload) do
11
+ {
12
+ "data" => {
13
+ "id" => "550e8400-e29b-41d4-a716-446655440000",
14
+ "type" => "photos",
15
+ "attributes" => {
16
+ "title" => "Ember Hamster 2",
17
+ "src" => "http://example.com/images/productivity-2.png"
18
+ },
19
+ "relationships" => {
20
+ "photographer" => {
21
+ "data" => { "type" => "people", "id" => "4b8a0af6-953d-4729-8b9a-1fa4eb18f3c9" }
22
+ }
23
+ }
24
+ }
25
+ }
26
+ end
27
+ let(:headers) do
28
+ {
29
+ "Content-Type" => "application/vnd.api+json",
30
+ "Accept" => "application/vnd.api+json"
31
+ }
32
+ end
33
+
34
+ before do
35
+ People::STORE["4b8a0af6-953d-4729-8b9a-1fa4eb18f3c9"] = {
36
+ id: "4b8a0af6-953d-4729-8b9a-1fa4eb18f3c9",
37
+ name: "Kurtis Rainbolt-Greene"
38
+ }
39
+ Photo::STORE["550e8400-e29b-41d4-a716-446655440000"] = {
40
+ id: "550e8400-e29b-41d4-a716-446655440000",
41
+ title: "Ember Hamster",
42
+ src: "http://example.com/images/productivity.png"
43
+ }
44
+ end
45
+
46
+ it "creates a model" do
47
+ expect(subject).to be_a_kind_of(Photo)
48
+ end
49
+
50
+ it "assigns the attributes" do
51
+ expect(subject).to have_attributes(title: "Ember Hamster 2", src: "http://example.com/images/productivity-2.png", updated_at: a_kind_of(Time))
52
+ end
53
+
54
+ it "relates the relationships" do
55
+ expect(subject).to have_attributes(photographer: a_kind_of(People))
56
+ end
57
+
58
+ it "saves the record" do
59
+ expect {subject}.to change {Photo::STORE}.from({"550e8400-e29b-41d4-a716-446655440000" => hash_including(id: "550e8400-e29b-41d4-a716-446655440000", title: "Ember Hamster", src: "http://example.com/images/productivity.png")}).to({"550e8400-e29b-41d4-a716-446655440000" => hash_including(id: "550e8400-e29b-41d4-a716-446655440000", title: "Ember Hamster 2", src: "http://example.com/images/productivity-2.png")})
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,33 @@
1
+ module JSONAPI
2
+ module Realizer
3
+ module Adapter
4
+ require_relative "adapter/active_record"
5
+ require_relative "adapter/memory"
6
+
7
+ MAPPINGS = {
8
+ memory: JSONAPI::Realizer::Adapter::Memory,
9
+ active_record: JSONAPI::Realizer::Adapter::ActiveRecord,
10
+ }
11
+
12
+ def self.adapt(resource, interface, &block)
13
+ if interface.kind_of?(Symbol)
14
+ if JSONAPI::Realizer::Adapter::MAPPINGS.key?(interface)
15
+ resource.include(JSONAPI::Realizer::Adapter::MAPPINGS.fetch(interface))
16
+ else
17
+ raise ArgumentError, "you've given an invalid adapter alias: #{interface}, we support #{JSONAPI::Realizer::Adapter::MAPPINGS.keys}"
18
+ end
19
+ else
20
+ resource.include(interface)
21
+ end
22
+
23
+ if block_given?
24
+ resource.instance_eval(&block)
25
+ end
26
+
27
+ raise ArgumentError, "need to provide a Adapter.find_via interface" unless resource.instance_variable_defined?(:@find_via_call)
28
+ raise ArgumentError, "need to provide a Adapter.write_attributes_via interface" unless resource.instance_variable_defined?(:@write_attributes_via_call)
29
+ raise ArgumentError, "need to provide a Adapter.save_via interface" unless resource.instance_variable_defined?(:@save_via_call)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,23 @@
1
+ module JSONAPI
2
+ module Realizer
3
+ module Adapter
4
+ module ActiveRecord
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ find_via do |model_class, id|
9
+ model_class.find(id)
10
+ end
11
+
12
+ write_attributes_via do |model, attributes|
13
+ model.assign_attributes(attributes)
14
+ end
15
+
16
+ save_via do |model|
17
+ model.save!
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,27 @@
1
+ module JSONAPI
2
+ module Realizer
3
+ module Adapter
4
+ module Memory
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ find_via do |model_class, id|
9
+ model_class.fetch(id)
10
+ end
11
+
12
+ write_attributes_via do |model, attributes|
13
+ model.assign_attributes(attributes)
14
+ end
15
+
16
+ save_via do |model|
17
+ model.assign_attributes(id: model.id || SecureRandom.uuid)
18
+ model.assign_attributes(updated_at: Time.now)
19
+ model_class.const_get("STORE")[model.id] = model_class.const_get("ATTRIBUTES").inject({}) do |hash, key|
20
+ hash.merge({ key => model.public_send(key) })
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,34 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe JSONAPI::Realizer::Adapter do
4
+ describe ".adapt" do
5
+ context "for the active_record mapped alias" do
6
+ it "defines the find_via_call instance variable as a anonymous function"
7
+ it "defines the find_via_call instance variable as a anonymous function"
8
+ end
9
+
10
+ context "for a mapped alias that doesn't exist" do
11
+
12
+ end
13
+
14
+ context "for a block defintion" do
15
+
16
+ end
17
+
18
+ context "for an alias and block defintion" do
19
+
20
+ end
21
+
22
+ context "when the find_via interface isn't defined" do
23
+
24
+ end
25
+
26
+ context "when the write_attributes_via interface isn't defined" do
27
+
28
+ end
29
+
30
+ context "when the save_via interface isn't defined" do
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,122 @@
1
+ module JSONAPI
2
+ module Realizer
3
+ class Resource
4
+ extend ActiveSupport::Concern
5
+
6
+ attr_reader :model
7
+
8
+ def initialize(model)
9
+ @model = model
10
+ end
11
+
12
+ def relationship(name)
13
+ relationships.public_send(name.to_sym)
14
+ end
15
+
16
+ def attribute(name)
17
+ relationships.public_send(name.to_sym)
18
+ end
19
+
20
+ private def attributes
21
+ configuration.attributes
22
+ end
23
+
24
+ private def relationships
25
+ configuration.relationships
26
+ end
27
+
28
+ private def as_relationship(value)
29
+ data = value.fetch("data")
30
+ mapping = JSONAPI::Realizer.mapping.fetch(data.fetch("type"))
31
+ mapping.resource_class.find_via_call(
32
+ mapping.model_class,
33
+ data.fetch("id")
34
+ )
35
+ end
36
+
37
+ private def model_class
38
+ configuration.model_class
39
+ end
40
+
41
+ private def configuration
42
+ self.class.configuration
43
+ end
44
+
45
+ def valid_attribute?(name, value)
46
+ attributes.respond_to?(name.to_sym)
47
+ end
48
+
49
+ def valid_relationship?(name, value)
50
+ relationships.respond_to?(name.to_sym)
51
+ end
52
+
53
+ def self.represents(type, class_name:)
54
+ @configuration = JSONAPI::Realizer.register(self, class_name.constantize, type.to_s)
55
+ end
56
+
57
+ def self.adapter(interface, &block)
58
+ JSONAPI::Realizer::Adapter.adapt(self, interface, &block)
59
+ end
60
+
61
+ def self.find_via(&finder)
62
+ @find_via_call = finder
63
+ end
64
+
65
+ def self.find_via_call(model_class, id)
66
+ @find_via_call.call(model_class, id)
67
+ end
68
+
69
+ def self.save_via(&saver)
70
+ @save_via_call = saver
71
+ end
72
+
73
+ def self.save_via_call(model)
74
+ @save_via_call.call(model)
75
+ end
76
+
77
+ def self.write_attributes_via(&writer)
78
+ @write_attributes_via_call = writer
79
+ end
80
+
81
+ def self.write_attributes_via_call(model, attributes)
82
+ @write_attributes_via_call.call(model, attributes)
83
+ end
84
+
85
+ def self.has_one(name, as: name)
86
+ relationships.public_send("#{name}=", OpenStruct.new({name: name, as: as}))
87
+ end
88
+
89
+ def self.has(name)
90
+ attributes.public_send("#{name}=", OpenStruct.new({name: name}))
91
+ end
92
+
93
+ def self.relationship(name)
94
+ relationships.public_send(name.to_sym)
95
+ end
96
+
97
+ def self.attribute(name)
98
+ relationships.public_send(name.to_sym)
99
+ end
100
+
101
+ def self.attributes
102
+ configuration.attributes
103
+ end
104
+
105
+ def self.relationships
106
+ configuration.relationships
107
+ end
108
+
109
+ def self.model_class
110
+ configuration.model_class
111
+ end
112
+
113
+ def self.configuration
114
+ if @configuration
115
+ @configuration
116
+ else
117
+ raise ArgumentError, "you need to have the resource configured"
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,5 @@
1
+ module JSONAPI
2
+ module Realizer
3
+ VERSION = "1.0.0"
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe JSONAPI::Realizer::VERSION do
4
+ it "should be a string" do
5
+ expect(JSONAPI::Realizer::VERSION).to be_kind_of(String)
6
+ end
7
+ end
@@ -0,0 +1,6 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe JSONAPI::Realizer do
4
+ it "on create generates a model with a relationship and a client id" do
5
+ end
6
+ end
metadata ADDED
@@ -0,0 +1,159 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jsonapi-realizer
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Kurtis Rainbolt-Greene
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-03-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.16'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.16'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.7'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '12.2'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '12.2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.11'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.11'
69
+ - !ruby/object:Gem::Dependency
70
+ name: activemodel
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '5.1'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '5.1'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry-doc
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.11'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.11'
97
+ - !ruby/object:Gem::Dependency
98
+ name: activesupport
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '5.1'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '5.1'
111
+ description: A way to take json:api requests and turn them into models
112
+ email:
113
+ - kurtis@rainbolt-greene.online
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - README.md
119
+ - Rakefile
120
+ - lib/jsonapi-realizer.rb
121
+ - lib/jsonapi/realizer.rb
122
+ - lib/jsonapi/realizer/action.rb
123
+ - lib/jsonapi/realizer/action/create.rb
124
+ - lib/jsonapi/realizer/action/create_spec.rb
125
+ - lib/jsonapi/realizer/action/update.rb
126
+ - lib/jsonapi/realizer/action/update_spec.rb
127
+ - lib/jsonapi/realizer/adapter.rb
128
+ - lib/jsonapi/realizer/adapter/active_record.rb
129
+ - lib/jsonapi/realizer/adapter/memory.rb
130
+ - lib/jsonapi/realizer/adapter_spec.rb
131
+ - lib/jsonapi/realizer/resource.rb
132
+ - lib/jsonapi/realizer/version.rb
133
+ - lib/jsonapi/realizer/version_spec.rb
134
+ - lib/jsonapi/realizer_spec.rb
135
+ homepage: http://krainboltgreene.github.io/jsonapi-realizer
136
+ licenses:
137
+ - ISC
138
+ metadata: {}
139
+ post_install_message:
140
+ rdoc_options: []
141
+ require_paths:
142
+ - lib
143
+ required_ruby_version: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ required_rubygems_version: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ requirements: []
154
+ rubyforge_project:
155
+ rubygems_version: 2.7.4
156
+ signing_key:
157
+ specification_version: 4
158
+ summary: A way to take json:api requests and turn them into models
159
+ test_files: []