grape_fast_jsonapi 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: ed838d297ef0c44b39588e77a204a37a8c8b4b4f
4
- data.tar.gz: 0e57addeb1bfeac8b6ff3e5c54ceb85d20f9cddb
2
+ SHA256:
3
+ metadata.gz: 38ad3fb865f43aa0c089abf0136617191d3dbf8fa10d3dff3798537312026851
4
+ data.tar.gz: 44f09504170ee1b3ec39be3d11784adaf5255b867693c77850d5089b2b2cecf5
5
5
  SHA512:
6
- metadata.gz: f65646281a1da90c7fb6e4d38918f67fe50c1467c3a54546b3a7a7d39e50189c907bf851c02b8bac01723196f038a842336e8f972a0772fd05d0b7b618fc9fa0
7
- data.tar.gz: 62e22336e61cec1388e2980dac12e045facf7fd77c7bb0a8c3ee94b9e1a7735904bfa21d2fa819425af9669758ef6f7e23003e712abf27a03f70c553d2d55cc9
6
+ metadata.gz: c6d628fe38e31362949ee2c9e7fbf9d866fe5e99ee910aa16f8dc533da1ee54ec5e8af949d688b194fbe783d258fe5ac09e20ee5a23d60ba8b1aa61335f4d1f7
7
+ data.tar.gz: c6f7ec14e0e3d67e9dd707dd99b563408d62526f4188c114198c53a8b053a0075c2c7f98bea028cf1baa797a613465ba7b0b8be16e431624bc961ae6dd00804c
@@ -0,0 +1,57 @@
1
+ # Ruby CircleCI 2.0 configuration file
2
+ #
3
+ # Check https://circleci.com/docs/2.0/language-ruby/ for more details
4
+ #
5
+ version: 2
6
+ jobs:
7
+ build:
8
+ docker:
9
+ # specify the version you desire here
10
+ - image: circleci/ruby:2.5.3-node-browsers
11
+ environment:
12
+ RAILS_ENV: test
13
+
14
+ # Specify service dependencies here if necessary
15
+ # CircleCI maintains a library of pre-built images
16
+ # documented at https://circleci.com/docs/2.0/circleci-images/
17
+
18
+ working_directory: ~/repo
19
+
20
+ steps:
21
+ - checkout
22
+
23
+ # Download and cache dependencies
24
+ - restore_cache:
25
+ keys:
26
+ - v1-dependencies-{{ checksum "Gemfile.lock" }}
27
+ # fallback to using the latest cache if no exact match is found
28
+ - v1-dependencies-
29
+
30
+ - run:
31
+ name: install gems
32
+ command: |
33
+ bundle install --jobs=4 --retry=3 --path vendor/bundle
34
+
35
+ - save_cache:
36
+ paths:
37
+ - ./vendor/bundle
38
+ key: v1-dependencies-{{ checksum "Gemfile.lock" }}
39
+
40
+ # run tests!
41
+ - run:
42
+ name: run tests
43
+ command: |
44
+ mkdir /tmp/test-results
45
+ TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)"
46
+
47
+ bundle exec rspec --format progress \
48
+ --out /tmp/test-results/rspec.xml \
49
+ --format progress \
50
+ $TEST_FILES
51
+
52
+ # collect reports
53
+ - store_test_results:
54
+ path: /tmp/test-results
55
+ - store_artifacts:
56
+ path: /tmp/test-results
57
+ destination: test-results
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --require spec_helper
3
+ --format documentation
data/CHANGELOG.md ADDED
@@ -0,0 +1,14 @@
1
+ ## Changelog
2
+
3
+ ### 0.2.1 (Next)
4
+
5
+ * Your contribution here.
6
+
7
+ ### v0.2.0 (February 8, 2019)
8
+
9
+ * [#5](https://github.com/EmCousin/grape_fast_jsonapi/pull/5): Provide custom Grape Swagger parser for fast_jsonapi object serializers, as well as unit test coverage - [@EmCousin](https://github.com/EmCousin)
10
+ * [#6](https://github.com/EmCousin/grape_fast_jsonapi/pull/6) - Fix to make the parser compatible with latest version of fast_jsonapi (1.5 at date) - @rromanchuk](https://github.com/rromanchuk).
11
+
12
+ ### v0.1.0
13
+
14
+ * Initial public release - [@EmCousin](https://github.com/EmCousin).
data/Gemfile.lock ADDED
@@ -0,0 +1,173 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ grape_fast_jsonapi (0.2.0)
5
+ fast_jsonapi (>= 1.5)
6
+ grape
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ actioncable (5.2.2)
12
+ actionpack (= 5.2.2)
13
+ nio4r (~> 2.0)
14
+ websocket-driver (>= 0.6.1)
15
+ actionmailer (5.2.2)
16
+ actionpack (= 5.2.2)
17
+ actionview (= 5.2.2)
18
+ activejob (= 5.2.2)
19
+ mail (~> 2.5, >= 2.5.4)
20
+ rails-dom-testing (~> 2.0)
21
+ actionpack (5.2.2)
22
+ actionview (= 5.2.2)
23
+ activesupport (= 5.2.2)
24
+ rack (~> 2.0)
25
+ rack-test (>= 0.6.3)
26
+ rails-dom-testing (~> 2.0)
27
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
28
+ actionview (5.2.2)
29
+ activesupport (= 5.2.2)
30
+ builder (~> 3.1)
31
+ erubi (~> 1.4)
32
+ rails-dom-testing (~> 2.0)
33
+ rails-html-sanitizer (~> 1.0, >= 1.0.3)
34
+ activejob (5.2.2)
35
+ activesupport (= 5.2.2)
36
+ globalid (>= 0.3.6)
37
+ activemodel (5.2.2)
38
+ activesupport (= 5.2.2)
39
+ activerecord (5.2.2)
40
+ activemodel (= 5.2.2)
41
+ activesupport (= 5.2.2)
42
+ arel (>= 9.0)
43
+ activestorage (5.2.2)
44
+ actionpack (= 5.2.2)
45
+ activerecord (= 5.2.2)
46
+ marcel (~> 0.3.1)
47
+ activesupport (5.2.2)
48
+ concurrent-ruby (~> 1.0, >= 1.0.2)
49
+ i18n (>= 0.7, < 2)
50
+ minitest (~> 5.1)
51
+ tzinfo (~> 1.1)
52
+ arel (9.0.0)
53
+ axiom-types (0.1.1)
54
+ descendants_tracker (~> 0.0.4)
55
+ ice_nine (~> 0.11.0)
56
+ thread_safe (~> 0.3, >= 0.3.1)
57
+ builder (3.2.3)
58
+ coercible (1.0.0)
59
+ descendants_tracker (~> 0.0.1)
60
+ concurrent-ruby (1.1.4)
61
+ crass (1.0.4)
62
+ descendants_tracker (0.0.4)
63
+ thread_safe (~> 0.3, >= 0.3.1)
64
+ diff-lcs (1.3)
65
+ equalizer (0.0.11)
66
+ erubi (1.8.0)
67
+ fast_jsonapi (1.5)
68
+ activesupport (>= 4.2)
69
+ globalid (0.4.2)
70
+ activesupport (>= 4.2.0)
71
+ grape (1.2.3)
72
+ activesupport
73
+ builder
74
+ mustermann-grape (~> 1.0.0)
75
+ rack (>= 1.3.0)
76
+ rack-accept
77
+ virtus (>= 1.0.0)
78
+ i18n (1.5.3)
79
+ concurrent-ruby (~> 1.0)
80
+ ice_nine (0.11.2)
81
+ loofah (2.2.3)
82
+ crass (~> 1.0.2)
83
+ nokogiri (>= 1.5.9)
84
+ mail (2.7.1)
85
+ mini_mime (>= 0.1.1)
86
+ marcel (0.3.3)
87
+ mimemagic (~> 0.3.2)
88
+ method_source (0.9.2)
89
+ mimemagic (0.3.3)
90
+ mini_mime (1.0.1)
91
+ mini_portile2 (2.4.0)
92
+ minitest (5.11.3)
93
+ mustermann (1.0.3)
94
+ mustermann-grape (1.0.0)
95
+ mustermann (~> 1.0.0)
96
+ nio4r (2.3.1)
97
+ nokogiri (1.10.1)
98
+ mini_portile2 (~> 2.4.0)
99
+ rack (2.0.6)
100
+ rack-accept (0.4.5)
101
+ rack (>= 0.4)
102
+ rack-test (1.1.0)
103
+ rack (>= 1.0, < 3)
104
+ rails (5.2.2)
105
+ actioncable (= 5.2.2)
106
+ actionmailer (= 5.2.2)
107
+ actionpack (= 5.2.2)
108
+ actionview (= 5.2.2)
109
+ activejob (= 5.2.2)
110
+ activemodel (= 5.2.2)
111
+ activerecord (= 5.2.2)
112
+ activestorage (= 5.2.2)
113
+ activesupport (= 5.2.2)
114
+ bundler (>= 1.3.0)
115
+ railties (= 5.2.2)
116
+ sprockets-rails (>= 2.0.0)
117
+ rails-dom-testing (2.0.3)
118
+ activesupport (>= 4.2.0)
119
+ nokogiri (>= 1.6)
120
+ rails-html-sanitizer (1.0.4)
121
+ loofah (~> 2.2, >= 2.2.2)
122
+ railties (5.2.2)
123
+ actionpack (= 5.2.2)
124
+ activesupport (= 5.2.2)
125
+ method_source
126
+ rake (>= 0.8.7)
127
+ thor (>= 0.19.0, < 2.0)
128
+ rake (12.3.2)
129
+ rspec (3.8.0)
130
+ rspec-core (~> 3.8.0)
131
+ rspec-expectations (~> 3.8.0)
132
+ rspec-mocks (~> 3.8.0)
133
+ rspec-core (3.8.0)
134
+ rspec-support (~> 3.8.0)
135
+ rspec-expectations (3.8.2)
136
+ diff-lcs (>= 1.2.0, < 2.0)
137
+ rspec-support (~> 3.8.0)
138
+ rspec-mocks (3.8.0)
139
+ diff-lcs (>= 1.2.0, < 2.0)
140
+ rspec-support (~> 3.8.0)
141
+ rspec-support (3.8.0)
142
+ sprockets (3.7.2)
143
+ concurrent-ruby (~> 1.0)
144
+ rack (> 1, < 3)
145
+ sprockets-rails (3.2.1)
146
+ actionpack (>= 4.0)
147
+ activesupport (>= 4.0)
148
+ sprockets (>= 3.0.0)
149
+ thor (0.20.3)
150
+ thread_safe (0.3.6)
151
+ tzinfo (1.2.5)
152
+ thread_safe (~> 0.1)
153
+ virtus (1.0.5)
154
+ axiom-types (~> 0.1)
155
+ coercible (~> 1.0)
156
+ descendants_tracker (~> 0.0, >= 0.0.3)
157
+ equalizer (~> 0.0, >= 0.0.9)
158
+ websocket-driver (0.7.0)
159
+ websocket-extensions (>= 0.1.0)
160
+ websocket-extensions (0.1.3)
161
+
162
+ PLATFORMS
163
+ ruby
164
+
165
+ DEPENDENCIES
166
+ fast_jsonapi
167
+ grape
168
+ grape_fast_jsonapi!
169
+ rails (>= 4.2.0)
170
+ rspec (~> 3.7)
171
+
172
+ BUNDLED WITH
173
+ 1.16.6
data/README.md CHANGED
@@ -8,14 +8,11 @@ Add the `grape` and `grape_fast_jsonapi` gems to Gemfile.
8
8
 
9
9
  ```ruby
10
10
  gem 'grape'
11
- # gem is not published to rubygems yet
12
- gem 'grape_fast_jsonapi', git: 'git@github.com:EmCousin/grape_fast_jsonapi.git'
11
+ gem 'grape_fast_jsonapi'
13
12
  ```
14
13
 
15
14
  ## Usage
16
15
 
17
- ### Require grape_fast_jsonapi
18
-
19
16
  ### Tell your API to use Grape::Formatter::FastJsonapi
20
17
 
21
18
  ```ruby
@@ -34,6 +31,33 @@ get "/" do
34
31
  end
35
32
  ```
36
33
 
34
+ ### Model parser for response documentation
35
+
36
+ When using Grape with Swagger via [grape-swagger](https://github.com/ruby-grape/grape-swagger), you can generate response documentation automatically via the provided following model parser:
37
+
38
+ ```ruby
39
+ # FastJsonapi serializer example
40
+ # app/serializers/user_serializer.rb
41
+ class UserSerializer
42
+ include FastJsonapi::ObjectSerializer
43
+
44
+ set_type :user
45
+ has_many :orders
46
+
47
+ attributes :name, :email
48
+ end
49
+
50
+ # config/initializers/grape_swagger.rb
51
+ GrapeSwagger.model_parsers.register(GrapeSwagger::FastJsonapi::Parser, UserSerializer)
52
+
53
+ # Your grape API endpoint
54
+ desc 'Get current user',
55
+ success: { code: 200, model: UserSerializer, message: 'The current user' }
56
+ # [...]
57
+ ```
58
+
59
+ Note that you **need** the `grape-swagger` gem for this to work, otherwise it will throw an error.
60
+
37
61
  ## Credit
38
62
 
39
63
  Code adapted from [grape-jsonapi-resources](https://github.com/cdunn/grape-jsonapi-resources)
@@ -19,10 +19,8 @@ Gem::Specification.new do |gem|
19
19
  gem.licenses = ['MIT']
20
20
 
21
21
  gem.add_dependency 'grape'
22
- gem.add_dependency 'fast_jsonapi'
22
+ gem.add_dependency 'fast_jsonapi', '>= 1.5'
23
23
 
24
- gem.add_development_dependency 'rails', '>= 5.0.0'
25
- gem.add_development_dependency 'rspec'
26
- gem.add_development_dependency 'rack-test'
27
- gem.add_development_dependency 'rake'
24
+ gem.add_development_dependency 'rails', '>= 4.2.0'
25
+ gem.add_development_dependency 'rspec', '~> 3.7'
28
26
  end
@@ -14,6 +14,8 @@ module Grape
14
14
  private
15
15
 
16
16
  def serializable?(object)
17
+ return false if object.nil?
18
+
17
19
  object.respond_to?(:serializable_hash) || object.respond_to?(:to_a) && object.all? { |o| o.respond_to? :serializable_hash } || object.is_a?(Hash)
18
20
  end
19
21
 
@@ -21,7 +23,7 @@ module Grape
21
23
  if object.respond_to? :serializable_hash
22
24
  serializable_object(object, fast_jsonapi_options(env)).serializable_hash
23
25
  elsif object.respond_to?(:to_a) && object.all? { |o| o.respond_to? :serializable_hash }
24
- fast_jsonapi_serializable(object, fast_jsonapi_options(env)).serializable_hash || object.map(&:serializable_hash)
26
+ serializable_collection(object, fast_jsonapi_options(env))
25
27
  elsif object.is_a?(Hash)
26
28
  serialize_each_pair(object, env)
27
29
  else
@@ -37,7 +39,18 @@ module Grape
37
39
  serializable_class(object)&.new(object, options)
38
40
  end
39
41
 
42
+ def serializable_collection(collection, options)
43
+ if collection.map(&:model_name).uniq.count > 1
44
+ collection.map do |o|
45
+ fast_jsonapi_serializable(o, options).serializable_hash || o.map(&:serializable_hash)
46
+ end
47
+ else
48
+ fast_jsonapi_serializable(collection, options).serializable_hash || collection.map(&:serializable_hash)
49
+ end
50
+ end
51
+
40
52
  def serializable_class(object)
53
+ object = object.first if object.is_a?(Array)
41
54
  (object.model_name.name + 'Serializer').safe_constantize
42
55
  end
43
56
 
@@ -0,0 +1,178 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GrapeSwagger
4
+ module FastJsonapi
5
+ class Parser
6
+ attr_reader :model
7
+ attr_reader :endpoint
8
+
9
+ def initialize(model, endpoint)
10
+ @model = model
11
+ @endpoint = endpoint
12
+ end
13
+
14
+ def call
15
+ schema = default_schema
16
+
17
+ attributes_hash = if (defined? ActiveRecord)
18
+ map_active_record_columns_to_attributes
19
+ else
20
+ map_model_attributes
21
+ end
22
+
23
+ attributes_hash.each do |attribute, type|
24
+ schema[:data][:properties][:attributes][:properties][attribute] = { type: type }
25
+ schema[:data][:example][:attributes][attribute] = send "#{type}_example"
26
+ end
27
+
28
+ relationships_hash = model.relationships_to_serialize || []
29
+
30
+ relationships_hash.each do |model_type, relationship_data|
31
+ relationships_attributes = relationship_data.instance_values.symbolize_keys
32
+ schema[:data][:properties][:relationships][:properties][model_type] = {
33
+ type: :object,
34
+ properties: relationships_properties(relationships_attributes)
35
+ }
36
+ schema[:data][:example][:relationships][model_type] = relationships_example(relationships_attributes)
37
+ end
38
+
39
+ schema
40
+ end
41
+
42
+ private
43
+
44
+ def default_schema
45
+ {
46
+ data: {
47
+ type: :object,
48
+ properties: {
49
+ id: { type: :integer },
50
+ type: { type: :string },
51
+ attributes: default_schema_object,
52
+ relationships: default_schema_object
53
+ },
54
+ example: {
55
+ id: 1,
56
+ type: model.record_type,
57
+ attributes: {},
58
+ relationships: {}
59
+ }
60
+ }
61
+ }
62
+ end
63
+
64
+ def default_schema_object
65
+ { type: :object, properties: {} }
66
+ end
67
+
68
+ def map_active_record_columns_to_attributes
69
+ activerecord_model = model.record_type.to_s.camelize.safe_constantize
70
+ return map_model_attributes unless activerecord_model&.is_a?(ActiveRecord::Base)
71
+
72
+ columns = activerecord_model.columns.select do |c|
73
+ c.name.to_sym.in?(model.attributes_to_serialize.keys)
74
+ end
75
+
76
+ attributes = {}
77
+ columns.each do |column|
78
+ attributes[column.name] = column.type
79
+ end
80
+
81
+ attributes
82
+ end
83
+
84
+ def map_model_attributes
85
+ attributes = {}
86
+ model.attributes_to_serialize.each do |attribute, _|
87
+ attributes[attribute] = :string
88
+ end
89
+ attributes
90
+ end
91
+
92
+ def relationships_properties(relationship_data)
93
+ if relationship_data[:relationship_type] == :has_many
94
+ {
95
+ data: {
96
+ type: :array,
97
+ items: relationship_default_item
98
+ }
99
+ }
100
+ else
101
+ {
102
+ data: relationship_default_item
103
+ }
104
+ end
105
+ end
106
+
107
+ def relationship_default_item
108
+ {
109
+ type: :object,
110
+ properties: {
111
+ id: { type: :integer },
112
+ type: { type: :string }
113
+ }
114
+ }
115
+ end
116
+
117
+ def relationships_example(relationship_data)
118
+ data = { id: 1, type: relationship_data[:record_type] }
119
+ if relationship_data[:relationship_type] == :has_many
120
+ { data: [data] }
121
+ else
122
+ { data: data }
123
+ end
124
+ end
125
+
126
+ def integer_example
127
+ if defined? Faker
128
+ Faker::Number.number.to_i
129
+ else
130
+ rand(1..9999)
131
+ end
132
+ end
133
+
134
+ def string_example
135
+ if defined? Faker
136
+ Faker::Lorem.word
137
+ else
138
+ "Example string"
139
+ end
140
+ end
141
+
142
+ def text_example
143
+ if defined? Faker
144
+ Faker::Lorem.paragraph
145
+ else
146
+ "Example string"
147
+ end
148
+ end
149
+
150
+ def date_example
151
+ Date.today.to_s
152
+ end
153
+
154
+ def datetime_example
155
+ Time.current.to_s
156
+ end
157
+ alias :time_example :datetime_example
158
+
159
+ def object_example
160
+ if defined? Faker
161
+ {
162
+ string_example.parameterize.underscore.to_sym => string_example.parameterize.underscore.to_sym
163
+ }
164
+ else
165
+ { example: :object }
166
+ end
167
+ end
168
+
169
+ def array_example
170
+ [string_example]
171
+ end
172
+
173
+ def boolean_example
174
+ [true, false].sample
175
+ end
176
+ end
177
+ end
178
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Grape
4
4
  module FastJsonapi
5
- VERSION = '0.1.0'
5
+ VERSION = '0.2.0'.freeze
6
6
  end
7
7
  end
@@ -1,5 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails'
1
4
  require 'fast_jsonapi'
2
5
  require 'grape'
3
6
  require 'grape_fast_jsonapi/endpoint_extension'
4
7
  require 'grape_fast_jsonapi/formatter'
8
+ require 'grape_fast_jsonapi/parser'
5
9
  require 'grape_fast_jsonapi/version'
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Grape::Formatter::FastJsonapi do
4
+ describe 'class methods' do
5
+ let(:user) do
6
+ User.new(id: 1, first_name: 'Chuck', last_name: 'Norris', password: 'supersecretpassword', email: 'chuck@norris.com')
7
+ end
8
+ let(:another_user) do
9
+ User.new(id: 2, first_name: 'Bruce', last_name: 'Lee', password: 'supersecretpassword', email: 'bruce@lee.com')
10
+ end
11
+ let(:blog_post) do
12
+ BlogPost.new(id: 1, title: "Blog Post title", body: "Blog post body")
13
+ end
14
+
15
+ describe '.call' do
16
+ subject { described_class.call(object, env) }
17
+ let(:env) { {} }
18
+
19
+ context 'when the object is a string' do
20
+ let(:object) { "I am a string" }
21
+
22
+ it { is_expected.to eq object }
23
+ end
24
+
25
+ context 'when the object is serializable' do
26
+ let(:user_serializer) { UserSerializer.new(object, {}) }
27
+ let(:blog_post_serializer) { BlogPostSerializer.new(object, {}) }
28
+
29
+ context 'when the object is a active serializable model instance' do
30
+ let(:object) { user }
31
+
32
+ it { is_expected.to eq ::Grape::Json.dump(user_serializer.serializable_hash) }
33
+ end
34
+
35
+ context 'when the object is an array of active serializable model instances' do
36
+ let(:object) { [user, another_user] }
37
+
38
+ it { is_expected.to eq ::Grape::Json.dump(user_serializer.serializable_hash) }
39
+
40
+ context "when the array contains instances of different models" do
41
+ let(:object) { [user, blog_post] }
42
+
43
+ it 'returns an array of jsonapi serialialized objects' do
44
+ expect(subject).to eq(::Grape::Json.dump([
45
+ UserSerializer.new(user, {}).serializable_hash,
46
+ BlogPostSerializer.new(blog_post, {}).serializable_hash
47
+ ]))
48
+ end
49
+ end
50
+ end
51
+
52
+ context 'when the object is a Hash of plain values' do
53
+ let(:object) { user.as_json }
54
+
55
+ it { is_expected.to eq ::Grape::Json.dump(object) }
56
+ end
57
+
58
+ context 'when the object is a Hash with serializable object values' do
59
+ let(:object) do
60
+ {
61
+ user: user,
62
+ blog_post: blog_post
63
+ }
64
+ end
65
+
66
+ it 'returns an hash of with jsonapi serialialized objects values' do
67
+ expect(subject).to eq(::Grape::Json.dump({
68
+ user: UserSerializer.new(user, {}).serializable_hash,
69
+ blog_post: BlogPostSerializer.new(blog_post, {}).serializable_hash
70
+ }))
71
+ end
72
+ end
73
+
74
+ context 'when the object is nil' do
75
+ let(:object) { nil }
76
+
77
+ it { is_expected.to eq 'null' }
78
+ end
79
+
80
+ context 'when the object is a number' do
81
+ let(:object) { 42 }
82
+
83
+ it { is_expected.to eq '42' }
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,131 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe GrapeSwagger::FastJsonapi::Parser do
4
+ let(:model) { BlogPostSerializer }
5
+ let(:endpoint) { '/' }
6
+
7
+ describe 'attr_readers' do
8
+ subject { described_class.new(model, endpoint) }
9
+
10
+ it { expect(subject.model).to eq model }
11
+ it { expect(subject.endpoint).to eq endpoint }
12
+ end
13
+
14
+ describe 'instance methods' do
15
+ describe '#call' do
16
+ subject { described_class.new(model, endpoint).call }
17
+
18
+ it 'return a hash defining the schema' do
19
+ expect(subject).to eq({
20
+ data: {
21
+ type: :object,
22
+ properties: {
23
+ id: { type: :integer },
24
+ type: { type: :string },
25
+ attributes: {
26
+ type: :object,
27
+ properties: {
28
+ title: { type: :string },
29
+ body: { type: :string }
30
+ }
31
+ },
32
+ relationships: {
33
+ type: :object,
34
+ properties: {
35
+ user: {
36
+ type: :object,
37
+ properties: {
38
+ data: {
39
+ type: :object,
40
+ properties: {
41
+ id: { type: :integer },
42
+ type: { type: :string }
43
+ }
44
+ }
45
+ }
46
+ }
47
+ }
48
+ }
49
+ },
50
+ example: {
51
+ id: 1,
52
+ type: :blog_post,
53
+ attributes: {
54
+ title: "Example string",
55
+ body: "Example string",
56
+ },
57
+ relationships: {
58
+ user: {
59
+ data: {
60
+ id: 1,
61
+ type: :user
62
+ }
63
+ }
64
+ }
65
+ }
66
+ }
67
+ })
68
+ end
69
+
70
+ context 'when the serializer contains sensitive information' do
71
+ let(:model) { UserSerializer } # contains :password attribute
72
+
73
+ it 'return a hash defining the schema filtering the sensitive attributes' do
74
+ expect(subject).to eq({
75
+ data: {
76
+ type: :object,
77
+ properties: {
78
+ id: { type: :integer },
79
+ type: { type: :string },
80
+ attributes: {
81
+ type: :object,
82
+ properties: {
83
+ first_name: { type: :string },
84
+ last_name: { type: :string },
85
+ email: { type: :string },
86
+ # password: { type: :string }, FILTERED
87
+ }
88
+ },
89
+ relationships: {
90
+ type: :object,
91
+ properties: {
92
+ blog_posts: {
93
+ type: :object,
94
+ properties: {
95
+ data: {
96
+ type: :array,
97
+ items: {
98
+ type: :object,
99
+ properties: {
100
+ id: { type: :integer },
101
+ type: { type: :string }
102
+ }
103
+ }
104
+ }
105
+ }
106
+ }
107
+ }
108
+ }
109
+ },
110
+ example: {
111
+ id: 1,
112
+ type: :user,
113
+ attributes: {
114
+ first_name: "Example string",
115
+ last_name: "Example string",
116
+ email: "Example string",
117
+ # password: "Example string", FILTERED
118
+ },
119
+ relationships: {
120
+ blog_posts: {
121
+ data: [{ id: 1, type: :blog_post }]
122
+ }
123
+ }
124
+ }
125
+ }
126
+ })
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Grape::FastJsonapi::VERSION do
4
+ it { is_expected.to eq '0.2.0' }
5
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_model'
4
+ require 'grape_fast_jsonapi'
5
+
6
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ class BlogPost
4
+ extend ActiveModel::Naming
5
+ include ActiveModel::Serialization
6
+
7
+ attr_accessor :id, :title, :body
8
+
9
+ def initialize(params = {})
10
+ params.each do |k, v|
11
+ instance_variable_set("@#{k}", v) unless v.nil?
12
+ end
13
+ end
14
+
15
+ def user_id
16
+ nil
17
+ end
18
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ class User
4
+ extend ActiveModel::Naming
5
+ include ActiveModel::Serialization
6
+
7
+ attr_accessor :id, :first_name, :last_name, :password, :email
8
+
9
+ def initialize(params = {})
10
+ params.each do |k, v|
11
+ instance_variable_set("@#{k}", v) unless v.nil?
12
+ end
13
+ end
14
+
15
+ def attributes
16
+ {
17
+ 'id' => nil,
18
+ 'first_name' => nil,
19
+ 'last_name' => nil,
20
+ 'password' => nil,
21
+ 'email' => nil
22
+ }
23
+ end
24
+
25
+ def blog_post_ids
26
+ []
27
+ end
28
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class BlogPostSerializer
4
+ include FastJsonapi::ObjectSerializer
5
+
6
+ belongs_to :user
7
+
8
+ attributes :title, :body
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UserSerializer
4
+ include FastJsonapi::ObjectSerializer
5
+
6
+ has_many :blog_posts
7
+
8
+ attributes :first_name, :last_name, :email
9
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grape_fast_jsonapi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Emmanuel Cousin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-06-06 00:00:00.000000000 Z
11
+ date: 2019-03-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: grape
@@ -30,70 +30,42 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: '1.5'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: '1.5'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rails
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: 5.0.0
47
+ version: 4.2.0
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: 5.0.0
54
+ version: 4.2.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: rack-test
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: rake
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
59
+ - - "~>"
88
60
  - !ruby/object:Gem::Version
89
- version: '0'
61
+ version: '3.7'
90
62
  type: :development
91
63
  prerelease: false
92
64
  version_requirements: !ruby/object:Gem::Requirement
93
65
  requirements:
94
- - - ">="
66
+ - - "~>"
95
67
  - !ruby/object:Gem::Version
96
- version: '0'
68
+ version: '3.7'
97
69
  description: Provides a Formatter for the Grape API DSL to emit objects serialized
98
70
  with fast_jsonapi.
99
71
  email:
@@ -102,7 +74,11 @@ executables: []
102
74
  extensions: []
103
75
  extra_rdoc_files: []
104
76
  files:
77
+ - ".circleci/config.yml"
78
+ - ".rspec"
79
+ - CHANGELOG.md
105
80
  - Gemfile
81
+ - Gemfile.lock
106
82
  - LICENSE
107
83
  - README.md
108
84
  - Rakefile
@@ -110,7 +86,16 @@ files:
110
86
  - lib/grape_fast_jsonapi.rb
111
87
  - lib/grape_fast_jsonapi/endpoint_extension.rb
112
88
  - lib/grape_fast_jsonapi/formatter.rb
89
+ - lib/grape_fast_jsonapi/parser.rb
113
90
  - lib/grape_fast_jsonapi/version.rb
91
+ - spec/lib/grape_fast_jsonapi/formatter_spec.rb
92
+ - spec/lib/grape_fast_jsonapi/parser_spec.rb
93
+ - spec/lib/grape_fast_jsonapi/version_spec.rb
94
+ - spec/spec_helper.rb
95
+ - spec/support/models/blog_post.rb
96
+ - spec/support/models/user.rb
97
+ - spec/support/serializers/blog_post_serializer.rb
98
+ - spec/support/serializers/user_serializer.rb
114
99
  homepage: https://github.com/EmCousin/grape_fast_jsonapi
115
100
  licenses:
116
101
  - MIT
@@ -130,9 +115,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
130
115
  - !ruby/object:Gem::Version
131
116
  version: '0'
132
117
  requirements: []
133
- rubyforge_project:
134
- rubygems_version: 2.5.2
118
+ rubygems_version: 3.0.1
135
119
  signing_key:
136
120
  specification_version: 4
137
121
  summary: Use fast_jsonapi in grape
138
- test_files: []
122
+ test_files:
123
+ - spec/lib/grape_fast_jsonapi/formatter_spec.rb
124
+ - spec/lib/grape_fast_jsonapi/parser_spec.rb
125
+ - spec/lib/grape_fast_jsonapi/version_spec.rb
126
+ - spec/spec_helper.rb
127
+ - spec/support/models/blog_post.rb
128
+ - spec/support/models/user.rb
129
+ - spec/support/serializers/blog_post_serializer.rb
130
+ - spec/support/serializers/user_serializer.rb