jsonapi_mapper 0.1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: '039bcb95b5c5b71d03c25ead00660671ad9a2db2'
4
+ data.tar.gz: bc0abb1fe5a9dd7b119367e5b91a0c1480e4e2ca
5
+ SHA512:
6
+ metadata.gz: 55ccb1660bcd748ddea0cb153e1b3342be87fbdee5b3a0e793b1e3a50b85e548c69f81bcedd8a893710fdb3342ef938782d46e8266b0cb9ce9255c8c1f74c917
7
+ data.tar.gz: a84cf5543ad7f79b3b02e8361139f263b1f7ea949971fb75c4bea93a14bf345fed0b0b997e2ea6ee46db3a4310769245dccbaf082be1ec891db9987109eb1a74
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.swp
11
+ *.swo
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.1
5
+ before_install: gem install bundler -v 1.15.4
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in jsonapi_mapper.gemspec
6
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 nubis
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,152 @@
1
+ # JsonapiMapper
2
+
3
+ Sanitizes a jsonapi Document and maps it to ActiveRecord, creating or updating as needed.
4
+ - Prevents assiginging unexpected attributes on your records.
5
+ - Prevents unscoped queries when creating/updating records.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'jsonapi_mapper'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install jsonapi_mapper
22
+
23
+ ## Usage
24
+
25
+ See the specs directory for more examples.
26
+
27
+ ```ruby
28
+ class Person < ActiveRecord::Base
29
+ belongs_to :parent, class_name: 'Person'
30
+ has_many :children, class_name: 'Person', foreign_key: 'parent_id'
31
+ belongs_to :pet, class_name: 'PetDog'
32
+ end
33
+
34
+ class PetDog < ActiveRecord::Base
35
+ has_one :person, foreign_key: 'pet_id'
36
+ end
37
+
38
+ # This document should create a person and several associations.
39
+ # Notice how these not-persisted resources can be referenced using
40
+ # an internal id, which starts with @
41
+ # The local @ ids shall be replaced with proper server assigned ids
42
+ # once the resources are persisted.
43
+ document = {
44
+ data: {
45
+ type: 'people',
46
+ attributes: { name: 'ian', admin: true },
47
+ relationships: {
48
+ pet: { data: { type: 'pet_dogs', id: '@1' }},
49
+ parent: { data: { type: 'people', id: '@1' }},
50
+ children: { data: [
51
+ { type: 'people', id: '@2' },
52
+ { type: 'people', id: '@3' },
53
+ ]},
54
+ }
55
+ },
56
+ included: [
57
+ { type: 'people', id: '@1', attributes: { name: 'ana', admin: true } },
58
+ { type: 'people', id: '@2', attributes: { name: 'bob', admin: true } },
59
+ { type: 'people', id: '@3', attributes: { name: 'zoe', admin: true } },
60
+ { type: 'pet_dogs', id: '@1', attributes: { name: 'ace', age: 11 } }
61
+ ]
62
+ }
63
+
64
+ # The mapper whitelists which types should be expected from the
65
+ # jsonapi document. It also whitelists attributes and relationship names.
66
+ # The last item of the attributes list is a Hash to be used as 'scope'
67
+ # when attempting to fetch and/or modify any resource.
68
+ mapper = JsonapiMapper.doc(document,
69
+ people: [:name, :pet, :parent, :children, country: 'argentina'],
70
+ pet_dogs: [:name, country: 'argentina']
71
+ )
72
+
73
+ person = mapper.data # This is the main document data as a new object
74
+ others = mapper.included # These are all the other resources.
75
+ mapper.save_all # Attempts to save both data and included.
76
+
77
+ # Four people have been created
78
+ Person.count.should == 4
79
+
80
+ # All of them from 'argentina' according to the provided scope.
81
+ Person.where(country: 'argentina').count.should == Person.count
82
+
83
+ # The 'admin' field was not set, because it wasn't in the mapper list.
84
+ Person.where(admin: true).count.should == 0
85
+
86
+ # This other document tries to update a bob's name and parent.
87
+ # And it also creates a new dow and assigns it as pet for 'bob' and 'ana'
88
+ other_document = {
89
+ data: {
90
+ type: 'people',
91
+ id: '1',
92
+ attributes: { name: 'rob' },
93
+ relationships: {
94
+ pet: { data: { type: 'pet_dogs', id: '@1' }},
95
+ parent: { data: { type: 'people', id: '2' }},
96
+ }
97
+ },
98
+ included: [
99
+ {
100
+ type: 'people',
101
+ id: ana.id,
102
+ relationships: {
103
+ pet: { data: { type: 'pet_dogs', id: '@1' }},
104
+ }
105
+ },
106
+ { type: 'pet_dogs', id: '@1', attributes: { name: 'ace' } }
107
+ ]
108
+ }
109
+
110
+ mapper = JsonapiMapper.doc other_document,
111
+ people: [:name, :pet, :parent, country: 'uruguay'],
112
+ pet_dogs: [:name, country: 'uruguay']
113
+
114
+ mapper.save_all
115
+
116
+ # Is dangerous to use unscoped queries
117
+ # For those rare occassions where you don't need them they can be disabled.
118
+ # The JsonapiMapper.doc_unsafe! method receives an argument with the names
119
+ # of all the types for which a scope is not required.
120
+ JsonapiMapper.doc_unsafe! document,
121
+ [:pet_dogs],
122
+ people: [:name, :pet, :parent, country: 'uruguay'],
123
+ pet_dogs: [:name]
124
+
125
+ # If you're needing to 'translate' between your jsonapi document names
126
+ # and your ActiveRecord class and column names, you can do it like so:
127
+ # Notice how the second hash has translations for type and attribute names.
128
+ mapper = JsonapiMapper.doc(document, {
129
+ persons: [:handle, :dog, :parental_figure, country: 'uruguay'],
130
+ pets: [:nickname, country: 'uruguay']
131
+ },
132
+ { types: { persons: Person, pets: PetDog },
133
+ attributes: {
134
+ persons: {handle: :name, dog: :pet, parental_figure: :parent},
135
+ pets: {nickname: :name},
136
+ }
137
+ }).save_all
138
+ ```
139
+
140
+ ## Development
141
+
142
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
143
+
144
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
145
+
146
+ ## Contributing
147
+
148
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/jsonapi_mapper.
149
+
150
+ ## License
151
+
152
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "jsonapi_mapper"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,38 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "jsonapi_mapper/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "jsonapi_mapper"
8
+ spec.version = JsonapiMapper::VERSION
9
+ spec.authors = ["nubis"]
10
+ spec.email = ["nb@bitex.la"]
11
+
12
+ spec.summary = %q{Sanitize and Map jsonapi documents straight into activemodels}
13
+ spec.description = %q{
14
+ Sanitizes a jsonapi Document and maps it to ActiveRecord,
15
+ creating or updating as needed.
16
+ Prevents mistakes when assigingng attributes or referring to
17
+ unscoped relationships.
18
+ }
19
+ spec.homepage = "https://github.com/bitex-la/jsonapi-mapper"
20
+ spec.license = "MIT"
21
+
22
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
23
+ f.match(%r{^(test|spec|features)/})
24
+ end
25
+ spec.bindir = "exe"
26
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
+ spec.require_paths = ["lib"]
28
+
29
+ spec.add_dependency "activesupport", '~> 4.2', '>= 4.2.0'
30
+ spec.add_dependency "activemodel",'~> 4.2', '>= 4.2.0'
31
+
32
+ spec.add_development_dependency "bundler", "~> 1.15"
33
+ spec.add_development_dependency "rake", "~> 10.0"
34
+ spec.add_development_dependency "rspec", "~> 3.0"
35
+ spec.add_development_dependency "activerecord", '~> 4.2', '>= 4.2.0'
36
+ spec.add_development_dependency "sqlite3", "~> 1.0", ">= 1.0.0"
37
+ spec.add_development_dependency "byebug", "~> 6.0", ">= 6.0.0"
38
+ end
@@ -0,0 +1,166 @@
1
+ require "jsonapi_mapper/version"
2
+
3
+ module JsonapiMapper
4
+ def self.doc(document, rules, renames = {})
5
+ DocumentMapper.new(document, [], rules, renames)
6
+ end
7
+
8
+ def self.doc_unsafe!(document, unscoped, rules, renames = {})
9
+ DocumentMapper.new(document, unscoped, rules, renames)
10
+ end
11
+
12
+ class RulesError < StandardError; end;
13
+
14
+ Id = Struct.new(:type, :raw)
15
+ Type = Struct.new(:name, :class, :rule)
16
+ Resource = Struct.new(:object, :relationships, :id)
17
+ Rule = Struct.new(:attributes, :scope)
18
+
19
+ class DocumentMapper
20
+ attr_accessor :document, :unscoped, :types, :renames, :resources,
21
+ :data, :included
22
+
23
+ def initialize(document, unscoped, rules, renames)
24
+ self.document = document.deep_symbolize_keys
25
+ self.renames = renames.deep_symbolize_keys
26
+ self.unscoped = unscoped.map(&:to_sym)
27
+ self.resources = {}
28
+
29
+ setup_types(rules)
30
+
31
+ main = if data = document[:data]
32
+ if data.is_a?(Array)
33
+ data.map{|r| build_resource(r) }.compact
34
+ else
35
+ build_resource(data)
36
+ end
37
+ end
38
+
39
+ rest = if included = document[:included]
40
+ included.map{|r| build_resource(r) }.compact
41
+ end
42
+
43
+ resources.each{|_,r| assign_relationships(r) }
44
+
45
+ self.data = main.is_a?(Array) ? main.map(&:object) : main.try(:object)
46
+ self.included = rest.try(:map, &:object)
47
+ end
48
+
49
+ def setup_types(rules)
50
+ self.types = {}
51
+ rules.each do |type_name, ruleset|
52
+ type_name = type_name.to_sym
53
+
54
+ attrs, scope = if ruleset.last.is_a?(Hash)
55
+ [ruleset[0..-2], ruleset.last]
56
+ else
57
+ unless unscoped.map(&:to_sym).include?(type_name)
58
+ raise RulesError.new("Missing Scope for #{type_name}")
59
+ end
60
+ [ruleset, {}]
61
+ end
62
+
63
+ unless attrs.all?{|v| v.is_a?(Symbol) || v.is_a?(String) }
64
+ raise RulesError.new('Attributes must be Strings or Symbols')
65
+ end
66
+
67
+ attrs = attrs.map(&:to_sym)
68
+ scope.symbolize_keys!
69
+
70
+ danger = scope.keys.to_set & attrs.map{|a| renamed(type_name, a) }.to_set
71
+ if danger.count > 0
72
+ raise RulesError.new("Don't let user set the scope: #{danger.to_a}")
73
+ end
74
+
75
+ cls = renames.fetch(:types, {})[type_name] ||
76
+ type_name.to_s.singularize.camelize.constantize
77
+
78
+ attrs.map{|a| renamed(type_name, a) }.each do |attr|
79
+ unless cls.new.respond_to?(attr)
80
+ raise NoMethodError.new("undefined method #{attr} for #{cls}")
81
+ end
82
+ end
83
+
84
+ types[type_name] = Type.new(type_name, cls, Rule.new(attrs, scope))
85
+ end
86
+ end
87
+
88
+ def build_resource(json)
89
+ return unless json.is_a? Hash
90
+ return unless json.fetch(:relationships, {}).is_a?(Hash)
91
+ return unless json.fetch(:attributes, {}).is_a?(Hash)
92
+ return unless type = types[json[:type].try(:to_sym)]
93
+
94
+ object = if json[:id].nil? || json[:id].to_s.starts_with?("@")
95
+ type.class.new.tap do |o|
96
+ type.rule.scope.each do |k,v|
97
+ o.send("#{k}=", v)
98
+ end
99
+ end
100
+ else
101
+ type.class.where(type.rule.scope).find(json[:id])
102
+ end
103
+
104
+ relationships = {}
105
+ json.fetch(:relationships, {}).each do |name, value|
106
+ next unless type.rule.attributes.include?(name)
107
+ relationships[renamed(type.name, name)] = if value[:data].is_a?(Array)
108
+ value[:data].map{|v| build_id(v) }
109
+ else
110
+ build_id(value[:data])
111
+ end
112
+ end
113
+
114
+ if attributes_to_be_set = json[:attributes]
115
+ type.rule.attributes.each do |name|
116
+ if value = attributes_to_be_set[name]
117
+ object.send("#{renamed(type.name, name)}=", value)
118
+ end
119
+ end
120
+ end
121
+
122
+ resource = Resource.new(object, relationships, build_id(json))
123
+ resources[resource.id] = resource
124
+ end
125
+
126
+ def build_id(json)
127
+ Id.new(json[:type].to_sym, json[:id])
128
+ end
129
+
130
+ def assign_relationships(resource)
131
+ resource.relationships.each do |name, ids|
132
+ if ids.is_a?(Array)
133
+ ids.each do |id|
134
+ next unless other = find_resource_object(id)
135
+ resource.object.send(name).push(other)
136
+ end
137
+ else
138
+ next unless other = find_resource_object(ids)
139
+ resource.object.send("#{name}=", other)
140
+ end
141
+ end
142
+ end
143
+
144
+ def find_resource_object(id)
145
+ return unless type = types[id.type]
146
+
147
+ resources[id].try(:object) ||
148
+ type.class.where(type.rule.scope).find(id.raw) or
149
+ raise ActiveRecord::RecordNotFound
150
+ .new("Couldn't find #{id.type} with id=#{id.raw}")
151
+ end
152
+
153
+ def renamed(type, attr)
154
+ renames.fetch(:attributes, {}).fetch(type, {}).fetch(attr, attr)
155
+ end
156
+
157
+ def save_all
158
+ data.is_a?(Array) ? data.each(&:save) : data.try(:save)
159
+ included.try(:each, &:save)
160
+ end
161
+
162
+ def collection?
163
+ data.is_a?(Array)
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,3 @@
1
+ module JsonapiMapper
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,200 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jsonapi_mapper
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - nubis
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-11-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.2'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 4.2.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '4.2'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 4.2.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: activemodel
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '4.2'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 4.2.0
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '4.2'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 4.2.0
53
+ - !ruby/object:Gem::Dependency
54
+ name: bundler
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '1.15'
60
+ type: :development
61
+ prerelease: false
62
+ version_requirements: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - "~>"
65
+ - !ruby/object:Gem::Version
66
+ version: '1.15'
67
+ - !ruby/object:Gem::Dependency
68
+ name: rake
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - "~>"
72
+ - !ruby/object:Gem::Version
73
+ version: '10.0'
74
+ type: :development
75
+ prerelease: false
76
+ version_requirements: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - "~>"
79
+ - !ruby/object:Gem::Version
80
+ version: '10.0'
81
+ - !ruby/object:Gem::Dependency
82
+ name: rspec
83
+ requirement: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - "~>"
86
+ - !ruby/object:Gem::Version
87
+ version: '3.0'
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - "~>"
93
+ - !ruby/object:Gem::Version
94
+ version: '3.0'
95
+ - !ruby/object:Gem::Dependency
96
+ name: activerecord
97
+ requirement: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - "~>"
100
+ - !ruby/object:Gem::Version
101
+ version: '4.2'
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: 4.2.0
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - "~>"
110
+ - !ruby/object:Gem::Version
111
+ version: '4.2'
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: 4.2.0
115
+ - !ruby/object:Gem::Dependency
116
+ name: sqlite3
117
+ requirement: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - "~>"
120
+ - !ruby/object:Gem::Version
121
+ version: '1.0'
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: 1.0.0
125
+ type: :development
126
+ prerelease: false
127
+ version_requirements: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '1.0'
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ version: 1.0.0
135
+ - !ruby/object:Gem::Dependency
136
+ name: byebug
137
+ requirement: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - "~>"
140
+ - !ruby/object:Gem::Version
141
+ version: '6.0'
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: 6.0.0
145
+ type: :development
146
+ prerelease: false
147
+ version_requirements: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - "~>"
150
+ - !ruby/object:Gem::Version
151
+ version: '6.0'
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ version: 6.0.0
155
+ description: "\n Sanitizes a jsonapi Document and maps it to ActiveRecord,\n creating
156
+ or updating as needed.\n Prevents mistakes when assigingng attributes or referring
157
+ to \n unscoped relationships.\n "
158
+ email:
159
+ - nb@bitex.la
160
+ executables: []
161
+ extensions: []
162
+ extra_rdoc_files: []
163
+ files:
164
+ - ".gitignore"
165
+ - ".rspec"
166
+ - ".travis.yml"
167
+ - Gemfile
168
+ - LICENSE.txt
169
+ - README.md
170
+ - Rakefile
171
+ - bin/console
172
+ - bin/setup
173
+ - jsonapi_mapper.gemspec
174
+ - lib/jsonapi_mapper.rb
175
+ - lib/jsonapi_mapper/version.rb
176
+ homepage: https://github.com/bitex-la/jsonapi-mapper
177
+ licenses:
178
+ - MIT
179
+ metadata: {}
180
+ post_install_message:
181
+ rdoc_options: []
182
+ require_paths:
183
+ - lib
184
+ required_ruby_version: !ruby/object:Gem::Requirement
185
+ requirements:
186
+ - - ">="
187
+ - !ruby/object:Gem::Version
188
+ version: '0'
189
+ required_rubygems_version: !ruby/object:Gem::Requirement
190
+ requirements:
191
+ - - ">="
192
+ - !ruby/object:Gem::Version
193
+ version: '0'
194
+ requirements: []
195
+ rubyforge_project:
196
+ rubygems_version: 2.6.11
197
+ signing_key:
198
+ specification_version: 4
199
+ summary: Sanitize and Map jsonapi documents straight into activemodels
200
+ test_files: []