grape-entity 1.0.2 → 1.0.3
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 +4 -4
- data/CHANGELOG.md +15 -4
- data/lib/grape_entity/entity.rb +6 -9
- data/lib/grape_entity/version.rb +1 -1
- metadata +10 -37
- data/.coveralls.yml +0 -1
- data/.github/dependabot.yml +0 -20
- data/.github/workflows/ci.yml +0 -41
- data/.gitignore +0 -43
- data/.rspec +0 -4
- data/.rubocop.yml +0 -89
- data/.rubocop_todo.yml +0 -55
- data/.yardopts +0 -2
- data/CONTRIBUTING.md +0 -118
- data/Dangerfile +0 -3
- data/Gemfile +0 -28
- data/Guardfile +0 -16
- data/RELEASING.md +0 -84
- data/Rakefile +0 -20
- data/UPGRADING.md +0 -40
- data/bench/serializing.rb +0 -105
- data/grape-entity.gemspec +0 -24
- data/spec/grape_entity/entity_spec.rb +0 -2238
- data/spec/grape_entity/exposure/nesting_exposure/nested_exposures_spec.rb +0 -56
- data/spec/grape_entity/exposure/represent_exposure_spec.rb +0 -30
- data/spec/grape_entity/exposure_spec.rb +0 -100
- data/spec/grape_entity/hash_spec.rb +0 -89
- data/spec/grape_entity/json_spec.rb +0 -7
- data/spec/grape_entity/options_spec.rb +0 -64
- data/spec/spec_helper.rb +0 -31
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
describe Grape::Entity::Exposure::NestingExposure::NestedExposures do
|
|
4
|
-
subject(:nested_exposures) { described_class.new([]) }
|
|
5
|
-
|
|
6
|
-
describe '#deep_complex_nesting?(entity)' do
|
|
7
|
-
it 'is reset when additional exposure is added' do
|
|
8
|
-
subject << Grape::Entity::Exposure.new(:x, {})
|
|
9
|
-
expect(subject.instance_variable_get(:@deep_complex_nesting)).to be_nil
|
|
10
|
-
subject.deep_complex_nesting?(subject)
|
|
11
|
-
expect(subject.instance_variable_get(:@deep_complex_nesting)).to_not be_nil
|
|
12
|
-
subject << Grape::Entity::Exposure.new(:y, {})
|
|
13
|
-
expect(subject.instance_variable_get(:@deep_complex_nesting)).to be_nil
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
it 'is reset when exposure is deleted' do
|
|
17
|
-
subject << Grape::Entity::Exposure.new(:x, {})
|
|
18
|
-
expect(subject.instance_variable_get(:@deep_complex_nesting)).to be_nil
|
|
19
|
-
subject.deep_complex_nesting?(subject)
|
|
20
|
-
expect(subject.instance_variable_get(:@deep_complex_nesting)).to_not be_nil
|
|
21
|
-
subject.delete_by(:x)
|
|
22
|
-
expect(subject.instance_variable_get(:@deep_complex_nesting)).to be_nil
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
it 'is reset when exposures are cleared' do
|
|
26
|
-
subject << Grape::Entity::Exposure.new(:x, {})
|
|
27
|
-
expect(subject.instance_variable_get(:@deep_complex_nesting)).to be_nil
|
|
28
|
-
subject.deep_complex_nesting?(subject)
|
|
29
|
-
expect(subject.instance_variable_get(:@deep_complex_nesting)).to_not be_nil
|
|
30
|
-
subject.clear
|
|
31
|
-
expect(subject.instance_variable_get(:@deep_complex_nesting)).to be_nil
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
describe '.delete_by' do
|
|
36
|
-
subject { nested_exposures.delete_by(*attributes) }
|
|
37
|
-
|
|
38
|
-
let(:attributes) { [:id] }
|
|
39
|
-
|
|
40
|
-
before do
|
|
41
|
-
nested_exposures << Grape::Entity::Exposure.new(:id, {})
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
it 'deletes matching exposure' do
|
|
45
|
-
is_expected.to eq []
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
context "when given attribute doesn't exists" do
|
|
49
|
-
let(:attributes) { [:foo] }
|
|
50
|
-
|
|
51
|
-
it 'deletes matching exposure' do
|
|
52
|
-
is_expected.to eq(nested_exposures)
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
describe Grape::Entity::Exposure::RepresentExposure do
|
|
4
|
-
subject(:exposure) { described_class.new(:foo, {}, {}, double, double) }
|
|
5
|
-
|
|
6
|
-
describe '#setup' do
|
|
7
|
-
subject { exposure.setup(using_class_name, subexposure) }
|
|
8
|
-
|
|
9
|
-
let(:using_class_name) { double(:using_class_name) }
|
|
10
|
-
let(:subexposure) { double(:subexposure) }
|
|
11
|
-
|
|
12
|
-
it 'sets using_class_name' do
|
|
13
|
-
expect { subject }.to change(exposure, :using_class_name).to(using_class_name)
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
it 'sets subexposure' do
|
|
17
|
-
expect { subject }.to change(exposure, :subexposure).to(subexposure)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
context 'when using_class is set' do
|
|
21
|
-
before do
|
|
22
|
-
exposure.using_class
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
it 'resets using_class' do
|
|
26
|
-
expect { subject }.to change(exposure, :using_class)
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
end
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
describe Grape::Entity::Exposure do
|
|
4
|
-
let(:fresh_class) { Class.new(Grape::Entity) }
|
|
5
|
-
let(:model) { double(attributes) }
|
|
6
|
-
let(:attributes) do
|
|
7
|
-
{
|
|
8
|
-
name: 'Bob Bobson',
|
|
9
|
-
email: 'bob@example.com',
|
|
10
|
-
birthday: Time.gm(2012, 2, 27),
|
|
11
|
-
fantasies: ['Unicorns', 'Double Rainbows', 'Nessy'],
|
|
12
|
-
characteristics: [
|
|
13
|
-
{ key: 'hair_color', value: 'brown' }
|
|
14
|
-
],
|
|
15
|
-
friends: [
|
|
16
|
-
double(name: 'Friend 1', email: 'friend1@example.com', characteristics: [], fantasies: [], birthday: Time.gm(2012, 2, 27), friends: []),
|
|
17
|
-
double(name: 'Friend 2', email: 'friend2@example.com', characteristics: [], fantasies: [], birthday: Time.gm(2012, 2, 27), friends: [])
|
|
18
|
-
]
|
|
19
|
-
}
|
|
20
|
-
end
|
|
21
|
-
let(:entity) { fresh_class.new(model) }
|
|
22
|
-
subject { fresh_class.find_exposure(:name) }
|
|
23
|
-
|
|
24
|
-
describe '#key' do
|
|
25
|
-
it 'returns the attribute if no :as is set' do
|
|
26
|
-
fresh_class.expose :name
|
|
27
|
-
expect(subject.key(entity)).to eq :name
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
it 'returns the :as alias if one exists' do
|
|
31
|
-
fresh_class.expose :name, as: :nombre
|
|
32
|
-
expect(subject.key(entity)).to eq :nombre
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
it 'returns the result if :as is a proc' do
|
|
36
|
-
fresh_class.expose :name, as: proc { object.name.reverse }
|
|
37
|
-
expect(subject.key(entity)).to eq(model.name.reverse)
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
it 'returns the result if :as is a lambda' do
|
|
41
|
-
fresh_class.expose :name, as: ->(obj, _opts) { obj.name.reverse }
|
|
42
|
-
expect(subject.key(entity)).to eq(model.name.reverse)
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
describe '#conditions_met?' do
|
|
47
|
-
it 'only passes through hash :if exposure if all attributes match' do
|
|
48
|
-
fresh_class.expose :name, if: { condition1: true, condition2: true }
|
|
49
|
-
|
|
50
|
-
expect(subject.conditions_met?(entity, {})).to be false
|
|
51
|
-
expect(subject.conditions_met?(entity, condition1: true)).to be false
|
|
52
|
-
expect(subject.conditions_met?(entity, condition1: true, condition2: true)).to be true
|
|
53
|
-
expect(subject.conditions_met?(entity, condition1: false, condition2: true)).to be false
|
|
54
|
-
expect(subject.conditions_met?(entity, condition1: true, condition2: true, other: true)).to be true
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
it 'looks for presence/truthiness if a symbol is passed' do
|
|
58
|
-
fresh_class.expose :name, if: :condition1
|
|
59
|
-
|
|
60
|
-
expect(subject.conditions_met?(entity, {})).to be false
|
|
61
|
-
expect(subject.conditions_met?(entity, condition1: true)).to be true
|
|
62
|
-
expect(subject.conditions_met?(entity, condition1: false)).to be false
|
|
63
|
-
expect(subject.conditions_met?(entity, condition1: nil)).to be false
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
it 'looks for absence/falsiness if a symbol is passed' do
|
|
67
|
-
fresh_class.expose :name, unless: :condition1
|
|
68
|
-
|
|
69
|
-
expect(subject.conditions_met?(entity, {})).to be true
|
|
70
|
-
expect(subject.conditions_met?(entity, condition1: true)).to be false
|
|
71
|
-
expect(subject.conditions_met?(entity, condition1: false)).to be true
|
|
72
|
-
expect(subject.conditions_met?(entity, condition1: nil)).to be true
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
it 'only passes through proc :if exposure if it returns truthy value' do
|
|
76
|
-
fresh_class.expose :name, if: ->(_, opts) { opts[:true] }
|
|
77
|
-
|
|
78
|
-
expect(subject.conditions_met?(entity, true: false)).to be false
|
|
79
|
-
expect(subject.conditions_met?(entity, true: true)).to be true
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
it 'only passes through hash :unless exposure if any attributes do not match' do
|
|
83
|
-
fresh_class.expose :name, unless: { condition1: true, condition2: true }
|
|
84
|
-
|
|
85
|
-
expect(subject.conditions_met?(entity, {})).to be true
|
|
86
|
-
expect(subject.conditions_met?(entity, condition1: true)).to be true
|
|
87
|
-
expect(subject.conditions_met?(entity, condition1: true, condition2: true)).to be false
|
|
88
|
-
expect(subject.conditions_met?(entity, condition1: false, condition2: true)).to be true
|
|
89
|
-
expect(subject.conditions_met?(entity, condition1: true, condition2: true, other: true)).to be false
|
|
90
|
-
expect(subject.conditions_met?(entity, condition1: false, condition2: false)).to be true
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
it 'only passes through proc :unless exposure if it returns falsy value' do
|
|
94
|
-
fresh_class.expose :name, unless: ->(_, opts) { opts[:true] == true }
|
|
95
|
-
|
|
96
|
-
expect(subject.conditions_met?(entity, true: false)).to be true
|
|
97
|
-
expect(subject.conditions_met?(entity, true: true)).to be false
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
end
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
describe Grape::Entity do
|
|
4
|
-
it 'except option for nested entity', :aggregate_failures do
|
|
5
|
-
module EntitySpec
|
|
6
|
-
class Address < Grape::Entity
|
|
7
|
-
expose :post, if: :full
|
|
8
|
-
expose :city
|
|
9
|
-
expose :street
|
|
10
|
-
expose :house
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
class AddressWithString < Grape::Entity
|
|
14
|
-
self.hash_access = :string
|
|
15
|
-
expose :post, if: :full
|
|
16
|
-
expose :city
|
|
17
|
-
expose :street
|
|
18
|
-
expose :house, expose_nil: false
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
class Company < Grape::Entity
|
|
22
|
-
expose :full_name, if: :full
|
|
23
|
-
expose :name
|
|
24
|
-
expose :address do |c, o|
|
|
25
|
-
Address.represent c[:address], Grape::Entity::Options.new(o.opts_hash.except(:full))
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
class CompanyWithString < Grape::Entity
|
|
30
|
-
self.hash_access = :string
|
|
31
|
-
expose :full_name, if: :full
|
|
32
|
-
expose :name
|
|
33
|
-
expose :address do |c, o|
|
|
34
|
-
AddressWithString.represent c['address'], Grape::Entity::Options.new(o.opts_hash.except(:full))
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
company = {
|
|
40
|
-
full_name: 'full_name',
|
|
41
|
-
name: 'name',
|
|
42
|
-
address: {
|
|
43
|
-
post: '123456',
|
|
44
|
-
city: 'city',
|
|
45
|
-
street: 'street',
|
|
46
|
-
house: 'house',
|
|
47
|
-
something_else: 'something_else'
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
company_with_string = {
|
|
52
|
-
'full_name' => 'full_name',
|
|
53
|
-
'name' => 'name',
|
|
54
|
-
'address' => {
|
|
55
|
-
'post' => '123456',
|
|
56
|
-
'city' => 'city',
|
|
57
|
-
'street' => 'street',
|
|
58
|
-
'house' => 'house',
|
|
59
|
-
'something_else' => 'something_else'
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
company_without_house_with_string = {
|
|
64
|
-
'full_name' => 'full_name',
|
|
65
|
-
'name' => 'name',
|
|
66
|
-
'address' => {
|
|
67
|
-
'post' => '123456',
|
|
68
|
-
'city' => 'city',
|
|
69
|
-
'street' => 'street',
|
|
70
|
-
'something_else' => 'something_else'
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
expect(EntitySpec::CompanyWithString.represent(company_with_string).serializable_hash).to eq \
|
|
75
|
-
company.slice(:name).merge(address: company[:address].slice(:city, :street, :house))
|
|
76
|
-
|
|
77
|
-
expect(EntitySpec::CompanyWithString.represent(company_without_house_with_string).serializable_hash).to eq \
|
|
78
|
-
company.slice(:name).merge(address: company[:address].slice(:city, :street))
|
|
79
|
-
|
|
80
|
-
expect(EntitySpec::CompanyWithString.represent(company_with_string, full: true).serializable_hash).to eq \
|
|
81
|
-
company.slice(:full_name, :name).merge(address: company[:address].slice(:city, :street, :house))
|
|
82
|
-
|
|
83
|
-
expect(EntitySpec::Company.represent(company).serializable_hash).to eq \
|
|
84
|
-
company.slice(:name).merge(address: company[:address].slice(:city, :street, :house))
|
|
85
|
-
|
|
86
|
-
expect(EntitySpec::Company.represent(company, full: true).serializable_hash).to eq \
|
|
87
|
-
company.slice(:full_name, :name).merge(address: company[:address].slice(:city, :street, :house))
|
|
88
|
-
end
|
|
89
|
-
end
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
describe Grape::Entity::Options do
|
|
4
|
-
module EntitySpec
|
|
5
|
-
class Crystalline
|
|
6
|
-
attr_accessor :prop1, :prop2, :prop3
|
|
7
|
-
|
|
8
|
-
def initialize
|
|
9
|
-
@prop1 = 'value1'
|
|
10
|
-
@prop2 = 'value2'
|
|
11
|
-
@prop3 = 'value3'
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
class CrystallineEntity < Grape::Entity
|
|
16
|
-
expose :prop1, if: ->(_, options) { options.fetch(:signal) }
|
|
17
|
-
expose :prop2, if: ->(_, options) { options.fetch(:beam, 'destructive') == 'destructive' }
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
context '#fetch' do
|
|
22
|
-
it 'without passing in a required option raises KeyError' do
|
|
23
|
-
expect { EntitySpec::CrystallineEntity.represent(EntitySpec::Crystalline.new).as_json }.to raise_error KeyError
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
it 'passing in a required option will expose the values' do
|
|
27
|
-
crystalline_entity = EntitySpec::CrystallineEntity.represent(EntitySpec::Crystalline.new, signal: true)
|
|
28
|
-
expect(crystalline_entity.as_json).to eq(prop1: 'value1', prop2: 'value2')
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
it 'with an option that is not default will not expose that value' do
|
|
32
|
-
crystalline_entity = EntitySpec::CrystallineEntity.represent(EntitySpec::Crystalline.new, signal: true, beam: 'intermittent')
|
|
33
|
-
expect(crystalline_entity.as_json).to eq(prop1: 'value1')
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
context '#dig', skip: !{}.respond_to?(:dig) do
|
|
38
|
-
let(:model_class) do
|
|
39
|
-
Class.new do
|
|
40
|
-
attr_accessor :prop1
|
|
41
|
-
|
|
42
|
-
def initialize
|
|
43
|
-
@prop1 = 'value1'
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
let(:entity_class) do
|
|
49
|
-
Class.new(Grape::Entity) do
|
|
50
|
-
expose :prop1, if: ->(_, options) { options.dig(:first, :second) == :nested }
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
it 'without passing in a expected option hide the value' do
|
|
55
|
-
entity = entity_class.represent(model_class.new, first: { invalid: :nested })
|
|
56
|
-
expect(entity.as_json).to eq({})
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
it 'passing in a expected option will expose the values' do
|
|
60
|
-
entity = entity_class.represent(model_class.new, first: { second: :nested })
|
|
61
|
-
expect(entity.as_json).to eq(prop1: 'value1')
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
end
|
data/spec/spec_helper.rb
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
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
|
-
# 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'
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
|
23
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
24
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'support'))
|
|
25
|
-
|
|
26
|
-
require 'rubygems'
|
|
27
|
-
require 'bundler'
|
|
28
|
-
|
|
29
|
-
Bundler.require :default, :test
|
|
30
|
-
|
|
31
|
-
RSpec.configure(&:raise_errors_for_deprecations!)
|