grape-entity 0.6.1 → 0.8.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.
Files changed (50) hide show
  1. checksums.yaml +5 -5
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +5 -1
  4. data/.rubocop.yml +82 -2
  5. data/.rubocop_todo.yml +16 -33
  6. data/.travis.yml +18 -17
  7. data/CHANGELOG.md +75 -0
  8. data/Dangerfile +2 -0
  9. data/Gemfile +6 -1
  10. data/Guardfile +4 -2
  11. data/README.md +101 -4
  12. data/Rakefile +2 -2
  13. data/UPGRADING.md +31 -2
  14. data/bench/serializing.rb +7 -0
  15. data/grape-entity.gemspec +10 -10
  16. data/lib/grape-entity.rb +2 -0
  17. data/lib/grape_entity.rb +3 -0
  18. data/lib/grape_entity/condition.rb +20 -11
  19. data/lib/grape_entity/condition/base.rb +3 -1
  20. data/lib/grape_entity/condition/block_condition.rb +3 -1
  21. data/lib/grape_entity/condition/hash_condition.rb +2 -0
  22. data/lib/grape_entity/condition/symbol_condition.rb +2 -0
  23. data/lib/grape_entity/delegator.rb +10 -9
  24. data/lib/grape_entity/delegator/base.rb +2 -0
  25. data/lib/grape_entity/delegator/fetchable_object.rb +2 -0
  26. data/lib/grape_entity/delegator/hash_object.rb +4 -2
  27. data/lib/grape_entity/delegator/openstruct_object.rb +2 -0
  28. data/lib/grape_entity/delegator/plain_object.rb +2 -0
  29. data/lib/grape_entity/deprecated.rb +13 -0
  30. data/lib/grape_entity/entity.rb +115 -36
  31. data/lib/grape_entity/exposure.rb +64 -41
  32. data/lib/grape_entity/exposure/base.rb +21 -8
  33. data/lib/grape_entity/exposure/block_exposure.rb +2 -0
  34. data/lib/grape_entity/exposure/delegator_exposure.rb +2 -0
  35. data/lib/grape_entity/exposure/formatter_block_exposure.rb +2 -0
  36. data/lib/grape_entity/exposure/formatter_exposure.rb +2 -0
  37. data/lib/grape_entity/exposure/nesting_exposure.rb +36 -30
  38. data/lib/grape_entity/exposure/nesting_exposure/nested_exposures.rb +26 -15
  39. data/lib/grape_entity/exposure/nesting_exposure/output_builder.rb +10 -2
  40. data/lib/grape_entity/exposure/represent_exposure.rb +3 -1
  41. data/lib/grape_entity/options.rb +44 -58
  42. data/lib/grape_entity/version.rb +3 -1
  43. data/spec/grape_entity/entity_spec.rb +270 -47
  44. data/spec/grape_entity/exposure/nesting_exposure/nested_exposures_spec.rb +6 -4
  45. data/spec/grape_entity/exposure/represent_exposure_spec.rb +5 -3
  46. data/spec/grape_entity/exposure_spec.rb +14 -2
  47. data/spec/grape_entity/hash_spec.rb +38 -1
  48. data/spec/grape_entity/options_spec.rb +66 -0
  49. data/spec/spec_helper.rb +17 -0
  50. metadata +32 -43
@@ -1,13 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Entity::Exposure::NestingExposure::NestedExposures do
4
6
  subject(:nested_exposures) { described_class.new([]) }
5
7
 
6
- describe '#deep_complex_nesting?' do
8
+ describe '#deep_complex_nesting?(entity)' do
7
9
  it 'is reset when additional exposure is added' do
8
10
  subject << Grape::Entity::Exposure.new(:x, {})
9
11
  expect(subject.instance_variable_get(:@deep_complex_nesting)).to be_nil
10
- subject.deep_complex_nesting?
12
+ subject.deep_complex_nesting?(subject)
11
13
  expect(subject.instance_variable_get(:@deep_complex_nesting)).to_not be_nil
12
14
  subject << Grape::Entity::Exposure.new(:y, {})
13
15
  expect(subject.instance_variable_get(:@deep_complex_nesting)).to be_nil
@@ -16,7 +18,7 @@ describe Grape::Entity::Exposure::NestingExposure::NestedExposures do
16
18
  it 'is reset when exposure is deleted' do
17
19
  subject << Grape::Entity::Exposure.new(:x, {})
18
20
  expect(subject.instance_variable_get(:@deep_complex_nesting)).to be_nil
19
- subject.deep_complex_nesting?
21
+ subject.deep_complex_nesting?(subject)
20
22
  expect(subject.instance_variable_get(:@deep_complex_nesting)).to_not be_nil
21
23
  subject.delete_by(:x)
22
24
  expect(subject.instance_variable_get(:@deep_complex_nesting)).to be_nil
@@ -25,7 +27,7 @@ describe Grape::Entity::Exposure::NestingExposure::NestedExposures do
25
27
  it 'is reset when exposures are cleared' do
26
28
  subject << Grape::Entity::Exposure.new(:x, {})
27
29
  expect(subject.instance_variable_get(:@deep_complex_nesting)).to be_nil
28
- subject.deep_complex_nesting?
30
+ subject.deep_complex_nesting?(subject)
29
31
  expect(subject.instance_variable_get(:@deep_complex_nesting)).to_not be_nil
30
32
  subject.clear
31
33
  expect(subject.instance_variable_get(:@deep_complex_nesting)).to be_nil
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Entity::Exposure::RepresentExposure do
@@ -10,11 +12,11 @@ describe Grape::Entity::Exposure::RepresentExposure do
10
12
  let(:subexposure) { double(:subexposure) }
11
13
 
12
14
  it 'sets using_class_name' do
13
- expect { subject }.to change { exposure.using_class_name }.to(using_class_name)
15
+ expect { subject }.to change(exposure, :using_class_name).to(using_class_name)
14
16
  end
15
17
 
16
18
  it 'sets subexposure' do
17
- expect { subject }.to change { exposure.subexposure }.to(subexposure)
19
+ expect { subject }.to change(exposure, :subexposure).to(subexposure)
18
20
  end
19
21
 
20
22
  context 'when using_class is set' do
@@ -23,7 +25,7 @@ describe Grape::Entity::Exposure::RepresentExposure do
23
25
  end
24
26
 
25
27
  it 'resets using_class' do
26
- expect { subject }.to change { exposure.using_class }
28
+ expect { subject }.to change(exposure, :using_class)
27
29
  end
28
30
  end
29
31
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Entity::Exposure do
@@ -24,12 +26,22 @@ describe Grape::Entity::Exposure do
24
26
  describe '#key' do
25
27
  it 'returns the attribute if no :as is set' do
26
28
  fresh_class.expose :name
27
- expect(subject.key).to eq :name
29
+ expect(subject.key(entity)).to eq :name
28
30
  end
29
31
 
30
32
  it 'returns the :as alias if one exists' do
31
33
  fresh_class.expose :name, as: :nombre
32
- expect(subject.key).to eq :nombre
34
+ expect(subject.key(entity)).to eq :nombre
35
+ end
36
+
37
+ it 'returns the result if :as is a proc' do
38
+ fresh_class.expose :name, as: proc { object.name.reverse }
39
+ expect(subject.key(entity)).to eq(model.name.reverse)
40
+ end
41
+
42
+ it 'returns the result if :as is a lambda' do
43
+ fresh_class.expose :name, as: ->(obj, _opts) { obj.name.reverse }
44
+ expect(subject.key(entity)).to eq(model.name.reverse)
33
45
  end
34
46
  end
35
47
 
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Entity do
4
- it 'except option for nested entity' do
6
+ it 'except option for nested entity', :aggregate_failures do
5
7
  module EntitySpec
6
8
  class Address < Grape::Entity
7
9
  expose :post, if: :full
@@ -10,6 +12,14 @@ describe Grape::Entity do
10
12
  expose :house
11
13
  end
12
14
 
15
+ class AddressWithString < Grape::Entity
16
+ self.hash_access = :string
17
+ expose :post, if: :full
18
+ expose :city
19
+ expose :street
20
+ expose :house
21
+ end
22
+
13
23
  class Company < Grape::Entity
14
24
  expose :full_name, if: :full
15
25
  expose :name
@@ -17,6 +27,15 @@ describe Grape::Entity do
17
27
  Address.represent c[:address], Grape::Entity::Options.new(o.opts_hash.except(:full))
18
28
  end
19
29
  end
30
+
31
+ class CompanyWithString < Grape::Entity
32
+ self.hash_access = :string
33
+ expose :full_name, if: :full
34
+ expose :name
35
+ expose :address do |c, o|
36
+ AddressWithString.represent c['address'], Grape::Entity::Options.new(o.opts_hash.except(:full))
37
+ end
38
+ end
20
39
  end
21
40
 
22
41
  company = {
@@ -31,6 +50,24 @@ describe Grape::Entity do
31
50
  }
32
51
  }
33
52
 
53
+ company_with_string = {
54
+ 'full_name' => 'full_name',
55
+ 'name' => 'name',
56
+ 'address' => {
57
+ 'post' => '123456',
58
+ 'city' => 'city',
59
+ 'street' => 'street',
60
+ 'house' => 'house',
61
+ 'something_else' => 'something_else'
62
+ }
63
+ }
64
+
65
+ expect(EntitySpec::CompanyWithString.represent(company_with_string).serializable_hash).to eq \
66
+ company.slice(:name).merge(address: company[:address].slice(:city, :street, :house))
67
+
68
+ expect(EntitySpec::CompanyWithString.represent(company_with_string, full: true).serializable_hash).to eq \
69
+ company.slice(:full_name, :name).merge(address: company[:address].slice(:city, :street, :house))
70
+
34
71
  expect(EntitySpec::Company.represent(company).serializable_hash).to eq \
35
72
  company.slice(:name).merge(address: company[:address].slice(:city, :street, :house))
36
73
 
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Grape::Entity::Options do
6
+ module EntitySpec
7
+ class Crystalline
8
+ attr_accessor :prop1, :prop2, :prop3
9
+
10
+ def initialize
11
+ @prop1 = 'value1'
12
+ @prop2 = 'value2'
13
+ @prop3 = 'value3'
14
+ end
15
+ end
16
+
17
+ class CrystallineEntity < Grape::Entity
18
+ expose :prop1, if: ->(_, options) { options.fetch(:signal) }
19
+ expose :prop2, if: ->(_, options) { options.fetch(:beam, 'destructive') == 'destructive' }
20
+ end
21
+ end
22
+
23
+ context '#fetch' do
24
+ it 'without passing in a required option raises KeyError' do
25
+ expect { EntitySpec::CrystallineEntity.represent(EntitySpec::Crystalline.new).as_json }.to raise_error KeyError
26
+ end
27
+
28
+ it 'passing in a required option will expose the values' do
29
+ crystalline_entity = EntitySpec::CrystallineEntity.represent(EntitySpec::Crystalline.new, signal: true)
30
+ expect(crystalline_entity.as_json).to eq(prop1: 'value1', prop2: 'value2')
31
+ end
32
+
33
+ it 'with an option that is not default will not expose that value' do
34
+ crystalline_entity = EntitySpec::CrystallineEntity.represent(EntitySpec::Crystalline.new, signal: true, beam: 'intermittent')
35
+ expect(crystalline_entity.as_json).to eq(prop1: 'value1')
36
+ end
37
+ end
38
+
39
+ context '#dig', skip: !{}.respond_to?(:dig) do
40
+ let(:model_class) do
41
+ Class.new do
42
+ attr_accessor :prop1
43
+
44
+ def initialize
45
+ @prop1 = 'value1'
46
+ end
47
+ end
48
+ end
49
+
50
+ let(:entity_class) do
51
+ Class.new(Grape::Entity) do
52
+ expose :prop1, if: ->(_, options) { options.dig(:first, :second) == :nested }
53
+ end
54
+ end
55
+
56
+ it 'without passing in a expected option hide the value' do
57
+ entity = entity_class.represent(model_class.new, first: { invalid: :nested })
58
+ expect(entity.as_json).to eq({})
59
+ end
60
+
61
+ it 'passing in a expected option will expose the values' do
62
+ entity = entity_class.represent(model_class.new, first: { second: :nested })
63
+ expect(entity.as_json).to eq(prop1: 'value1')
64
+ end
65
+ end
66
+ end
@@ -1,3 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'simplecov'
4
+ require 'coveralls'
5
+
6
+ # This works around the hash extensions not being automatically included in ActiveSupport < 4
7
+ require 'active_support/version'
8
+ require 'active_support/core_ext/hash' if ActiveSupport::VERSION &&
9
+ ActiveSupport::VERSION::MAJOR &&
10
+ ActiveSupport::VERSION::MAJOR < 4
11
+
12
+ SimpleCov.start do
13
+ add_filter 'spec/'
14
+ end
15
+
16
+ Coveralls.wear! unless RUBY_PLATFORM.eql? 'java'
17
+
1
18
  $LOAD_PATH.unshift(File.dirname(__FILE__))
2
19
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
20
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'support'))
metadata CHANGED
@@ -1,43 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grape-entity
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Bleigh
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-09 00:00:00.000000000 Z
11
+ date: 2020-11-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: multi_json
14
+ name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 1.3.2
19
+ version: 3.0.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 1.3.2
26
+ version: 3.0.0
27
27
  - !ruby/object:Gem::Dependency
28
- name: activesupport
28
+ name: multi_json
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 5.0.0
33
+ version: 1.3.2
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: 5.0.0
40
+ version: 1.3.2
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: rake
56
+ name: maruku
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -67,35 +67,21 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: rubocop
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '0.40'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '0.40'
83
- - !ruby/object:Gem::Dependency
84
- name: rspec
70
+ name: pry
85
71
  requirement: !ruby/object:Gem::Requirement
86
72
  requirements:
87
- - - "~>"
73
+ - - ">="
88
74
  - !ruby/object:Gem::Version
89
- version: '3.0'
75
+ version: '0'
90
76
  type: :development
91
77
  prerelease: false
92
78
  version_requirements: !ruby/object:Gem::Requirement
93
79
  requirements:
94
- - - "~>"
80
+ - - ">="
95
81
  - !ruby/object:Gem::Version
96
- version: '3.0'
82
+ version: '0'
97
83
  - !ruby/object:Gem::Dependency
98
- name: rack-test
84
+ name: pry-byebug
99
85
  requirement: !ruby/object:Gem::Requirement
100
86
  requirements:
101
87
  - - ">="
@@ -109,7 +95,7 @@ dependencies:
109
95
  - !ruby/object:Gem::Version
110
96
  version: '0'
111
97
  - !ruby/object:Gem::Dependency
112
- name: maruku
98
+ name: rack-test
113
99
  requirement: !ruby/object:Gem::Requirement
114
100
  requirements:
115
101
  - - ">="
@@ -123,7 +109,7 @@ dependencies:
123
109
  - !ruby/object:Gem::Version
124
110
  version: '0'
125
111
  - !ruby/object:Gem::Dependency
126
- name: yard
112
+ name: rake
127
113
  requirement: !ruby/object:Gem::Requirement
128
114
  requirements:
129
115
  - - ">="
@@ -137,21 +123,21 @@ dependencies:
137
123
  - !ruby/object:Gem::Version
138
124
  version: '0'
139
125
  - !ruby/object:Gem::Dependency
140
- name: pry
126
+ name: rspec
141
127
  requirement: !ruby/object:Gem::Requirement
142
128
  requirements:
143
- - - ">="
129
+ - - "~>"
144
130
  - !ruby/object:Gem::Version
145
- version: '0'
131
+ version: '3.9'
146
132
  type: :development
147
133
  prerelease: false
148
134
  version_requirements: !ruby/object:Gem::Requirement
149
135
  requirements:
150
- - - ">="
136
+ - - "~>"
151
137
  - !ruby/object:Gem::Version
152
- version: '0'
138
+ version: '3.9'
153
139
  - !ruby/object:Gem::Dependency
154
- name: pry-byebug
140
+ name: yard
155
141
  requirement: !ruby/object:Gem::Requirement
156
142
  requirements:
157
143
  - - ">="
@@ -172,6 +158,7 @@ executables: []
172
158
  extensions: []
173
159
  extra_rdoc_files: []
174
160
  files:
161
+ - ".coveralls.yml"
175
162
  - ".gitignore"
176
163
  - ".rspec"
177
164
  - ".rubocop.yml"
@@ -203,6 +190,7 @@ files:
203
190
  - lib/grape_entity/delegator/hash_object.rb
204
191
  - lib/grape_entity/delegator/openstruct_object.rb
205
192
  - lib/grape_entity/delegator/plain_object.rb
193
+ - lib/grape_entity/deprecated.rb
206
194
  - lib/grape_entity/entity.rb
207
195
  - lib/grape_entity/exposure.rb
208
196
  - lib/grape_entity/exposure/base.rb
@@ -221,12 +209,13 @@ files:
221
209
  - spec/grape_entity/exposure/represent_exposure_spec.rb
222
210
  - spec/grape_entity/exposure_spec.rb
223
211
  - spec/grape_entity/hash_spec.rb
212
+ - spec/grape_entity/options_spec.rb
224
213
  - spec/spec_helper.rb
225
214
  homepage: https://github.com/ruby-grape/grape-entity
226
215
  licenses:
227
216
  - MIT
228
217
  metadata: {}
229
- post_install_message:
218
+ post_install_message:
230
219
  rdoc_options: []
231
220
  require_paths:
232
221
  - lib
@@ -234,16 +223,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
234
223
  requirements:
235
224
  - - ">="
236
225
  - !ruby/object:Gem::Version
237
- version: 2.2.6
226
+ version: '2.4'
238
227
  required_rubygems_version: !ruby/object:Gem::Requirement
239
228
  requirements:
240
229
  - - ">="
241
230
  - !ruby/object:Gem::Version
242
231
  version: '0'
243
232
  requirements: []
244
- rubyforge_project: grape-entity
245
- rubygems_version: 2.6.8
246
- signing_key:
233
+ rubygems_version: 3.2.0.rc.1
234
+ signing_key:
247
235
  specification_version: 4
248
236
  summary: A simple facade for managing the relationship between your model and API.
249
237
  test_files:
@@ -252,4 +240,5 @@ test_files:
252
240
  - spec/grape_entity/exposure/represent_exposure_spec.rb
253
241
  - spec/grape_entity/exposure_spec.rb
254
242
  - spec/grape_entity/hash_spec.rb
243
+ - spec/grape_entity/options_spec.rb
255
244
  - spec/spec_helper.rb