grape-entity 0.9.0 → 0.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 040fece8639b5fd085e4c77f1c88172e686e2655adf5e1cbb80aa0bb06c46faf
4
- data.tar.gz: f688469ee710ac98ed822d41c3724f47d1ec8b6f9aa067eead52c07662c45121
3
+ metadata.gz: 4a89222a95fe66dc86d907762352275aa328a0423a461e2f5a7c8fc806a92f09
4
+ data.tar.gz: a06ad75430e568a7e4cd2e9b6b329011e8382003c5882f690199403be58928c7
5
5
  SHA512:
6
- metadata.gz: 3f14751f855805e0ea16f5c232a67c70c76d7523075a93ad442de9a31c9eb04816c1deae576d0e68671f6126790e7ca7d96bc8a7da4aa7c61d06f00385863c69
7
- data.tar.gz: 2d683f2414287de225b0d47e615f91563daf3b73c74e674c24cd2a1c6c2a417098ce0118e23d7272bf165d2895cb09fab824d52dfcb069dbfd8ea6e860b03b63
6
+ metadata.gz: 1bc3419fea51eb0c7c7c78f8f4e510c9d73bfe210cee2aa1f2aaaee92725d02334ab235818a37300c733c0970c9ee40cf56a022b421937ec6662d3e67da3e85f
7
+ data.tar.gz: 4f31cb8e01fbba21883bbf432fa557d0ca7f85d3c1d42a0aac0e4143c4add3af37e7f24b4fc315ff55502a640bffa0d185e8c3081d8a8b5492d45dc1b0102233
@@ -12,3 +12,9 @@ updates:
12
12
  day: "friday"
13
13
  assignees:
14
14
  - "LeFnord"
15
+ - package-ecosystem: "github-actions"
16
+ directory: "/"
17
+ schedule:
18
+ interval: weekly
19
+ assignees:
20
+ - "LeFnord"
@@ -0,0 +1,41 @@
1
+ name: Ruby
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - '*'
7
+ pull_request:
8
+ branches:
9
+ - '*'
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ jobs:
15
+ rubocop:
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - uses: actions/checkout@v3
19
+ - uses: ruby/setup-ruby@v1
20
+ with:
21
+ ruby-version: '3.1'
22
+ bundler-cache: true
23
+ - name: Run rubocop
24
+ run: bundle exec rubocop --parallel --format progress
25
+
26
+ rspec:
27
+ runs-on: ubuntu-latest
28
+ needs: ['rubocop']
29
+ strategy:
30
+ matrix:
31
+ ruby-version: ['2.7', '3.0', '3.1', 'head', jruby, truffleruby]
32
+ steps:
33
+ - name: Check out branch
34
+ uses: actions/checkout@v3
35
+ - name: Set up Ruby
36
+ uses: ruby/setup-ruby@v1
37
+ with:
38
+ ruby-version: ${{ matrix.ruby-version }}
39
+ bundler-cache: true
40
+ - name: Run rspec rest of the suite
41
+ run: bundle exec rspec
data/.rspec CHANGED
@@ -1,2 +1,3 @@
1
- --format documentation
2
1
  --color
2
+ --profile
3
+ --format documentation
data/.rubocop.yml CHANGED
@@ -5,7 +5,7 @@ AllCops:
5
5
  - vendor/**/*
6
6
  - example/**/*
7
7
  NewCops: enable
8
- TargetRubyVersion: 3.0
8
+ TargetRubyVersion: 3.1
9
9
  SuggestExtensions: false
10
10
 
11
11
  # Layout stuff
@@ -77,6 +77,9 @@ Naming:
77
77
  Style/Documentation:
78
78
  Enabled: false
79
79
 
80
+ Style/HashSyntax:
81
+ Enabled: false
82
+
80
83
  Style/OptionalBooleanParameter:
81
84
  AllowedMethods:
82
85
  # from lib/grape_entity/condition/base.rb
data/.rubocop_todo.yml CHANGED
@@ -1,11 +1,27 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2020-11-07 00:01:40 UTC using RuboCop version 1.2.0.
3
+ # on 2022-07-26 21:29:59 UTC using RuboCop version 1.32.0.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
7
7
  # versions of RuboCop, may require this file to be generated again.
8
8
 
9
+ # Offense count: 1
10
+ # This cop supports safe autocorrection (--autocorrect).
11
+ # Configuration parameters: Include.
12
+ # Include: **/*.gemspec
13
+ Gemspec/DeprecatedAttributeAssignment:
14
+ Exclude:
15
+ - 'grape-entity.gemspec'
16
+
17
+ # Offense count: 1
18
+ # This cop supports safe autocorrection (--autocorrect).
19
+ # Configuration parameters: Include.
20
+ # Include: **/*.gemspec
21
+ Gemspec/RequireMFA:
22
+ Exclude:
23
+ - 'grape-entity.gemspec'
24
+
9
25
  # Offense count: 1
10
26
  # Configuration parameters: Include.
11
27
  # Include: **/*.gemspec
@@ -14,14 +30,20 @@ Gemspec/RequiredRubyVersion:
14
30
  - 'grape-entity.gemspec'
15
31
 
16
32
  # Offense count: 6
17
- # Cop supports --auto-correct.
33
+ # This cop supports unsafe autocorrection (--autocorrect-all).
18
34
  Lint/BooleanSymbol:
19
35
  Exclude:
20
36
  - 'spec/grape_entity/exposure_spec.rb'
21
37
 
22
- # Offense count: 1
23
- # Cop supports --auto-correct.
24
- # Configuration parameters: IgnoredMethods.
38
+ # Offense count: 15
39
+ Style/OpenStructUse:
40
+ Exclude:
41
+ - 'lib/grape_entity/delegator.rb'
42
+ - 'spec/grape_entity/entity_spec.rb'
43
+
44
+ # Offense count: 2
45
+ # This cop supports unsafe autocorrection (--autocorrect-all).
46
+ # Configuration parameters: AllowMethodsWithArguments, IgnoredMethods, AllowComments.
25
47
  # IgnoredMethods: respond_to, define_method
26
48
  Style/SymbolProc:
27
49
  Exclude:
data/CHANGELOG.md CHANGED
@@ -9,6 +9,33 @@
9
9
  * Your contribution here.
10
10
 
11
11
 
12
+ ### 0.10.2 (2022-07-29)
13
+
14
+ #### Fixes
15
+
16
+ * [#366](https://github.com/ruby-grape/grape-entity/pull/366): Don't suppress regular ArgumentError exceptions - [splattael](https://github.com/splattael).
17
+ * [#363](https://github.com/ruby-grape/grape-entity/pull/338): Fix typo - [@OuYangJinTing](https://github.com/OuYangJinTing).
18
+ * [#361](https://github.com/ruby-grape/grape-entity/pull/361): Require 'active_support/core_ext' - [@pravi](https://github.com/pravi).
19
+
20
+
21
+ ### 0.10.1 (2021-10-22)
22
+
23
+ #### Fixes
24
+
25
+ * [#359](https://github.com/ruby-grape/grape-entity/pull/359): Respect `hash_access` setting when using `expose_nil: false` option - [@magni-](https://github.com/magni-).
26
+
27
+
28
+ ### 0.10.0 (2021-09-15)
29
+
30
+ #### Features
31
+
32
+ * [#352](https://github.com/ruby-grape/grape-entity/pull/352): Add Default value option - [@ahmednaguib](https://github.com/ahmednaguib).
33
+
34
+ #### Fixes
35
+
36
+ * [#355](https://github.com/ruby-grape/grape-entity/pull/355): Fix infinite loop problem with the `NameErrors` in block exposures - [@meinac](https://github.com/meinac).
37
+
38
+
12
39
  ### 0.9.0 (2021-03-20)
13
40
 
14
41
  #### Features
data/CONTRIBUTING.md CHANGED
@@ -78,7 +78,7 @@ git push origin my-feature-branch
78
78
 
79
79
  #### Make a Pull Request
80
80
 
81
- Go to https://github.com/contributor/grape-entity and select your feature branch. Click the 'Pull Request' button and fill out the form. Pull requests are usually reviewed within a few days.
81
+ Go to https://github.com/ruby-grape/grape-entity and select your feature branch. Click the 'Pull Request' button and fill out the form. Pull requests are usually reviewed within a few days.
82
82
 
83
83
  #### Rebase
84
84
 
data/README.md CHANGED
@@ -24,6 +24,7 @@
24
24
  - [Aliases](#aliases)
25
25
  - [Format Before Exposing](#format-before-exposing)
26
26
  - [Expose Nil](#expose-nil)
27
+ - [Default Value](#default-value)
27
28
  - [Documentation](#documentation)
28
29
  - [Options Hash](#options-hash)
29
30
  - [Passing Additional Option To Nested Exposure](#passing-additional-option-to-nested-exposure)
@@ -110,6 +111,20 @@ The field lookup takes several steps
110
111
  * next try `object.fetch(exposure)`
111
112
  * last raise an Exception
112
113
 
114
+ `exposure` is a Symbol by default. If `object` is a Hash with stringified keys, you can set the hash accessor at the entity-class level to properly expose its members:
115
+
116
+ ```ruby
117
+ class Status < GrapeEntity
118
+ self.hash_access = :to_s
119
+
120
+ expose :code
121
+ expose :message
122
+ end
123
+
124
+ Status.represent({ 'code' => 418, 'message' => "I'm a teapot" }).as_json
125
+ #=> { code: 418, message: "I'm a teapot" }
126
+ ```
127
+
113
128
  #### Exposing with a Presenter
114
129
 
115
130
  Don't derive your model classes from `Grape::Entity`, expose them using a presenter.
@@ -482,6 +497,19 @@ module Entities
482
497
  end
483
498
  ```
484
499
 
500
+ #### Default Value
501
+
502
+ This option can be used to provide a default value in case the return value is nil or empty.
503
+
504
+ ```ruby
505
+ module Entities
506
+ class MyModel < Grape::Entity
507
+ expose :name, default: ''
508
+ expose :age, default: 60
509
+ end
510
+ end
511
+ ```
512
+
485
513
  #### Documentation
486
514
 
487
515
  Expose documentation with the field. Gets bubbled up when used with Grape and various API documentation systems.
@@ -13,6 +13,11 @@ module Grape
13
13
  def delegatable?(_attribute)
14
14
  true
15
15
  end
16
+
17
+ def accepts_options?
18
+ # Why not `arity > 1`? It might be negative https://ruby-doc.org/core-2.6.6/Method.html#method-i-arity
19
+ method(:delegate).arity != 1
20
+ end
16
21
  end
17
22
  end
18
23
  end
@@ -11,10 +11,14 @@ module Grape
11
11
  module Delegator
12
12
  def self.new(object)
13
13
  delegator_klass =
14
- if object.is_a?(Hash) then HashObject
15
- elsif defined?(OpenStruct) && object.is_a?(OpenStruct) then OpenStructObject
16
- elsif object.respond_to?(:fetch, true) then FetchableObject
17
- else PlainObject
14
+ if object.is_a?(Hash)
15
+ HashObject
16
+ elsif defined?(OpenStruct) && object.is_a?(OpenStruct)
17
+ OpenStructObject
18
+ elsif object.respond_to?(:fetch, true)
19
+ FetchableObject
20
+ else
21
+ PlainObject
18
22
  end
19
23
 
20
24
  delegator_klass.new(object)
@@ -153,7 +153,7 @@ module Grape
153
153
  #
154
154
  # @example as: a proc or lambda
155
155
  #
156
- # object = OpenStruct(awesomness: 'awesome_key', awesome: 'not-my-key', other: 'other-key' )
156
+ # object = OpenStruct(awesomeness: 'awesome_key', awesome: 'not-my-key', other: 'other-key' )
157
157
  #
158
158
  # class MyEntity < Grape::Entity
159
159
  # expose :awesome, as: proc { object.awesomeness }
@@ -481,9 +481,6 @@ module Grape
481
481
  @object = object
482
482
  @options = options.is_a?(Options) ? options : Options.new(options)
483
483
  @delegator = Delegator.new(object)
484
-
485
- # Why not `arity > 1`? It might be negative https://ruby-doc.org/core-2.6.6/Method.html#method-i-arity
486
- @delegator_accepts_opts = @delegator.method(:delegate).arity != 1
487
484
  end
488
485
 
489
486
  def root_exposures
@@ -525,9 +522,12 @@ module Grape
525
522
  end
526
523
  rescue StandardError => e
527
524
  # it handles: https://github.com/ruby/ruby/blob/v3_0_0_preview1/NEWS.md#language-changes point 3, Proc
528
- raise Grape::Entity::Deprecated.new e.message, 'in ruby 3.0' if e.is_a?(ArgumentError)
525
+ # accounting for expose :foo, &:bar
526
+ if e.is_a?(ArgumentError) && block.parameters == [[:req], [:rest]]
527
+ raise Grape::Entity::Deprecated.new e.message, 'in ruby 3.0'
528
+ end
529
529
 
530
- raise e.class, e.message
530
+ raise e
531
531
  end
532
532
 
533
533
  def exec_with_attribute(attribute, &block)
@@ -541,7 +541,7 @@ module Grape
541
541
  def delegate_attribute(attribute)
542
542
  if is_defined_in_entity?(attribute)
543
543
  send(attribute)
544
- elsif @delegator_accepts_opts
544
+ elsif delegator.accepts_options?
545
545
  delegator.delegate(attribute, **self.class.delegation_opts)
546
546
  else
547
547
  delegator.delegate(attribute)
@@ -585,6 +585,7 @@ module Grape
585
585
  merge
586
586
  expose_nil
587
587
  override
588
+ default
588
589
  ].to_set.freeze
589
590
 
590
591
  # Merges the given options with current block options.
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'active_support'
4
+ require 'active_support/core_ext'
5
+
3
6
  module Grape
4
7
  class Entity
5
8
  module Exposure
@@ -16,6 +19,7 @@ module Grape
16
19
  key = options[:as] || attribute
17
20
  @key = key.respond_to?(:to_sym) ? key.to_sym : key
18
21
  @is_safe = options[:safe]
22
+ @default_value = options[:default]
19
23
  @for_merge = options[:merge]
20
24
  @attr_path_proc = options[:attr_path]
21
25
  @documentation = options[:documentation]
@@ -82,7 +86,10 @@ module Grape
82
86
  end
83
87
 
84
88
  def valid_value(entity, options)
85
- value(entity, options) if valid?(entity)
89
+ return unless valid?(entity)
90
+
91
+ output = value(entity, options)
92
+ output.blank? && @default_value.present? ? @default_value : output
86
93
  end
87
94
 
88
95
  def should_return_key?(options)
@@ -56,7 +56,12 @@ module Grape
56
56
  Condition.new_unless(
57
57
  proc do |object, _options|
58
58
  if options[:proc].nil?
59
- Delegator.new(object).delegate(attribute).nil?
59
+ delegator = Delegator.new(object)
60
+ if is_a?(Grape::Entity) && delegator.accepts_options?
61
+ delegator.delegate(attribute, **self.class.delegation_opts).nil?
62
+ else
63
+ delegator.delegate(attribute).nil?
64
+ end
60
65
  else
61
66
  exec_with_object(options, &options[:proc]).nil?
62
67
  end
@@ -9,7 +9,7 @@ module Grape
9
9
 
10
10
  attr_reader :opts_hash
11
11
 
12
- def_delegators :opts_hash, :dig, :key?, :fetch, :[], :empty
12
+ def_delegators :opts_hash, :dig, :key?, :fetch, :[], :empty?
13
13
 
14
14
  def initialize(opts_hash = {})
15
15
  @opts_hash = opts_hash
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GrapeEntity
4
- VERSION = '0.9.0'
4
+ VERSION = '0.10.2'
5
5
  end
@@ -30,9 +30,7 @@ describe Grape::Entity do
30
30
 
31
31
  it 'makes sure that :format_with as a proc cannot be used with a block' do
32
32
  # rubocop:disable Style/BlockDelimiters
33
- # rubocop:disable Lint/EmptyBlock
34
33
  expect { subject.expose :name, format_with: proc {} do p 'hi' end }.to raise_error ArgumentError
35
- # rubocop:enable Lint/EmptyBlock
36
34
  # rubocop:enable Style/BlockDelimiters
37
35
  end
38
36
 
@@ -214,6 +212,130 @@ describe Grape::Entity do
214
212
  end
215
213
  end
216
214
 
215
+ context 'with :default option' do
216
+ let(:a) { nil }
217
+ let(:b) { nil }
218
+ let(:c) { 'value' }
219
+
220
+ context 'when model is a PORO' do
221
+ let(:model) { Model.new(a, b, c) }
222
+
223
+ before do
224
+ stub_const 'Model', Class.new
225
+ Model.class_eval do
226
+ attr_accessor :a, :b, :c
227
+
228
+ def initialize(a, b, c)
229
+ @a = a
230
+ @b = b
231
+ @c = c
232
+ end
233
+ end
234
+ end
235
+
236
+ context 'when default option is not provided' do
237
+ it 'exposes attributes values' do
238
+ subject.expose(:a)
239
+ subject.expose(:b)
240
+ subject.expose(:c)
241
+ expect(subject.represent(model).serializable_hash).to eq(a: nil, b: nil, c: 'value')
242
+ end
243
+ end
244
+
245
+ context 'when default option is set' do
246
+ it 'exposes default values for attributes' do
247
+ subject.expose(:a, default: 'a')
248
+ subject.expose(:b, default: 'b')
249
+ subject.expose(:c, default: 'c')
250
+ expect(subject.represent(model).serializable_hash).to eq(a: 'a', b: 'b', c: 'value')
251
+ end
252
+ end
253
+
254
+ context 'when default option is set and block passed' do
255
+ it 'return default value if block returns nil' do
256
+ subject.expose(:a, default: 'a') do |_obj, _options|
257
+ nil
258
+ end
259
+ subject.expose(:b)
260
+ subject.expose(:c)
261
+ expect(subject.represent(model).serializable_hash).to eq(a: 'a', b: nil, c: 'value')
262
+ end
263
+
264
+ it 'return value from block if block returns a value' do
265
+ subject.expose(:a, default: 'a') do |_obj, _options|
266
+ 100
267
+ end
268
+ subject.expose(:b)
269
+ subject.expose(:c)
270
+ expect(subject.represent(model).serializable_hash).to eq(a: 100, b: nil, c: 'value')
271
+ end
272
+ end
273
+ end
274
+
275
+ context 'when model is a hash' do
276
+ let(:model) { { a: a, b: b, c: c } }
277
+
278
+ context 'when expose_nil option is not provided' do
279
+ it 'exposes nil attributes' do
280
+ subject.expose(:a)
281
+ subject.expose(:b)
282
+ subject.expose(:c)
283
+ expect(subject.represent(model).serializable_hash).to eq(a: nil, b: nil, c: 'value')
284
+ end
285
+ end
286
+
287
+ context 'when expose_nil option is true' do
288
+ it 'exposes nil attributes' do
289
+ subject.expose(:a, expose_nil: true)
290
+ subject.expose(:b, expose_nil: true)
291
+ subject.expose(:c)
292
+ expect(subject.represent(model).serializable_hash).to eq(a: nil, b: nil, c: 'value')
293
+ end
294
+ end
295
+
296
+ context 'when expose_nil option is false' do
297
+ it 'does not expose nil attributes' do
298
+ subject.expose(:a, expose_nil: false)
299
+ subject.expose(:b, expose_nil: false)
300
+ subject.expose(:c)
301
+ expect(subject.represent(model).serializable_hash).to eq(c: 'value')
302
+ end
303
+
304
+ it 'is only applied per attribute' do
305
+ subject.expose(:a, expose_nil: false)
306
+ subject.expose(:b)
307
+ subject.expose(:c)
308
+ expect(subject.represent(model).serializable_hash).to eq(b: nil, c: 'value')
309
+ end
310
+
311
+ it 'raises an error when applied to multiple attribute exposures' do
312
+ expect { subject.expose(:a, :b, :c, expose_nil: false) }.to raise_error ArgumentError
313
+ end
314
+ end
315
+ end
316
+
317
+ context 'with nested structures' do
318
+ let(:model) { { a: a, b: b, c: { d: nil, e: nil, f: { g: nil, h: nil } } } }
319
+
320
+ context 'when expose_nil option is false' do
321
+ it 'does not expose nil attributes' do
322
+ subject.expose(:a, expose_nil: false)
323
+ subject.expose(:b)
324
+ subject.expose(:c) do
325
+ subject.expose(:d, expose_nil: false)
326
+ subject.expose(:e)
327
+ subject.expose(:f) do
328
+ subject.expose(:g, expose_nil: false)
329
+ subject.expose(:h)
330
+ end
331
+ end
332
+
333
+ expect(subject.represent(model).serializable_hash).to eq(b: nil, c: { e: nil, f: { h: nil } })
334
+ end
335
+ end
336
+ end
337
+ end
338
+
217
339
  context 'with a block' do
218
340
  it 'errors out if called with multiple attributes' do
219
341
  expect { subject.expose(:name, :email) { true } }.to raise_error ArgumentError
@@ -267,6 +389,10 @@ describe Grape::Entity do
267
389
  def method_without_args
268
390
  'result'
269
391
  end
392
+
393
+ def raises_argument_error
394
+ raise ArgumentError, 'something different'
395
+ end
270
396
  end
271
397
 
272
398
  describe 'with block passed in' do
@@ -280,6 +406,17 @@ describe Grape::Entity do
280
406
  value = subject.represent(object).value_for(:that_method_without_args)
281
407
  expect(value).to eq('result')
282
408
  end
409
+
410
+ it 'does not suppress ArgumentError' do
411
+ subject.expose :raises_argument_error do |object|
412
+ object.raises_argument_error
413
+ end
414
+
415
+ object = SomeObject.new
416
+ expect do
417
+ subject.represent(object).value_for(:raises_argument_error)
418
+ end.to raise_error(ArgumentError, 'something different')
419
+ end
283
420
  end
284
421
 
285
422
  context 'with block passed in via &' do
@@ -1137,6 +1274,18 @@ describe Grape::Entity do
1137
1274
  expect(representation).to eq(id: nil, name: nil, user: { id: nil, name: nil, email: nil })
1138
1275
  end
1139
1276
  end
1277
+
1278
+ context 'when NameError happens in a parameterized block_exposure' do
1279
+ before do
1280
+ subject.expose :raise_no_method_error do |_|
1281
+ foo
1282
+ end
1283
+ end
1284
+
1285
+ it 'does not cause infinite loop' do
1286
+ expect { subject.represent({}, serializable: true) }.to raise_error(NameError)
1287
+ end
1288
+ end
1140
1289
  end
1141
1290
  end
1142
1291
 
@@ -1581,7 +1730,7 @@ describe Grape::Entity do
1581
1730
  end
1582
1731
 
1583
1732
  fresh_class.class_eval do
1584
- expose :characteristics, using: EntitySpec::NoPathCharacterEntity, attr_path: proc { nil }
1733
+ expose :characteristics, using: EntitySpec::NoPathCharacterEntity, attr_path: proc {}
1585
1734
  end
1586
1735
 
1587
1736
  expect(subject.serializable_hash).to eq(
@@ -17,7 +17,7 @@ describe Grape::Entity do
17
17
  expose :post, if: :full
18
18
  expose :city
19
19
  expose :street
20
- expose :house
20
+ expose :house, expose_nil: false
21
21
  end
22
22
 
23
23
  class Company < Grape::Entity
@@ -62,9 +62,23 @@ describe Grape::Entity do
62
62
  }
63
63
  }
64
64
 
65
+ company_without_house_with_string = {
66
+ 'full_name' => 'full_name',
67
+ 'name' => 'name',
68
+ 'address' => {
69
+ 'post' => '123456',
70
+ 'city' => 'city',
71
+ 'street' => 'street',
72
+ 'something_else' => 'something_else'
73
+ }
74
+ }
75
+
65
76
  expect(EntitySpec::CompanyWithString.represent(company_with_string).serializable_hash).to eq \
66
77
  company.slice(:name).merge(address: company[:address].slice(:city, :street, :house))
67
78
 
79
+ expect(EntitySpec::CompanyWithString.represent(company_without_house_with_string).serializable_hash).to eq \
80
+ company.slice(:name).merge(address: company[:address].slice(:city, :street))
81
+
68
82
  expect(EntitySpec::CompanyWithString.represent(company_with_string, full: true).serializable_hash).to eq \
69
83
  company.slice(:full_name, :name).merge(address: company[:address].slice(:city, :street, :house))
70
84
 
data/spec/spec_helper.rb CHANGED
@@ -9,12 +9,16 @@ require 'active_support/core_ext/hash' if ActiveSupport::VERSION &&
9
9
  ActiveSupport::VERSION::MAJOR &&
10
10
  ActiveSupport::VERSION::MAJOR < 4
11
11
 
12
- SimpleCov.start do
13
- add_filter 'spec/'
12
+ # Skip code covarge on Ruby >= 3.1
13
+ # See https://github.com/simplecov-ruby/simplecov/issues/1003
14
+ unless RUBY_VERSION >= '3.1'
15
+ SimpleCov.start do
16
+ add_filter 'spec/'
17
+ end
18
+
19
+ Coveralls.wear! unless RUBY_PLATFORM.eql? 'java'
14
20
  end
15
21
 
16
- Coveralls.wear! unless RUBY_PLATFORM.eql? 'java'
17
-
18
22
  $LOAD_PATH.unshift(File.dirname(__FILE__))
19
23
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
20
24
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'support'))
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grape-entity
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.10.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Bleigh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-20 00:00:00.000000000 Z
11
+ date: 2022-07-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -160,8 +160,7 @@ extra_rdoc_files: []
160
160
  files:
161
161
  - ".coveralls.yml"
162
162
  - ".github/dependabot.yml"
163
- - ".github/workflows/rubocop.yml"
164
- - ".github/workflows/ruby.yml"
163
+ - ".github/workflows/ci.yml"
165
164
  - ".gitignore"
166
165
  - ".rspec"
167
166
  - ".rubocop.yml"
@@ -232,7 +231,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
232
231
  - !ruby/object:Gem::Version
233
232
  version: '0'
234
233
  requirements: []
235
- rubygems_version: 3.2.3
234
+ rubygems_version: 3.3.7
236
235
  signing_key:
237
236
  specification_version: 4
238
237
  summary: A simple facade for managing the relationship between your model and API.
@@ -1,26 +0,0 @@
1
- name: Rubocop
2
-
3
- on:
4
- push:
5
- branches:
6
- - '*'
7
- pull_request:
8
- branches:
9
- - '*'
10
-
11
- jobs:
12
- rubocop:
13
- name: Rubocop
14
- runs-on: ubuntu-latest
15
- steps:
16
- - uses: actions/checkout@v2
17
- - uses: actions/setup-ruby@v1
18
- with:
19
- ruby-version: '3.0'
20
- - run: gem install rubocop --no-doc
21
- - run: rubocop --format progress --format json --out rubocop.json
22
- id: rubocop
23
- - uses: duderman/rubocop-annotate-action@v0.1.0
24
- with:
25
- path: rubocop.json
26
- if: ${{ failure() }}
@@ -1,26 +0,0 @@
1
- name: Ruby
2
-
3
- on:
4
- push:
5
- branches:
6
- - '*'
7
- pull_request:
8
- branches:
9
- - '*'
10
-
11
- jobs:
12
- spec:
13
- runs-on: ubuntu-latest
14
- strategy:
15
- matrix:
16
- ruby-version: ['2.6', '2.7', '3.0', head, jruby, truffleruby]
17
-
18
- steps:
19
- - uses: actions/checkout@v2
20
- - name: Set up Ruby
21
- uses: ruby/setup-ruby@v1
22
- with:
23
- ruby-version: ${{ matrix.ruby-version }}
24
- bundler-cache: true
25
- - name: Run rspec
26
- run: bundle exec rspec