grape-entity 0.6.0 → 0.10.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.coveralls.yml +1 -0
- data/.github/dependabot.yml +14 -0
- data/.github/workflows/rubocop.yml +26 -0
- data/.github/workflows/ruby.yml +26 -0
- data/.gitignore +5 -1
- data/.rspec +2 -1
- data/.rubocop.yml +82 -2
- data/.rubocop_todo.yml +16 -33
- data/CHANGELOG.md +120 -0
- data/Dangerfile +2 -0
- data/Gemfile +8 -8
- data/Guardfile +4 -2
- data/README.md +168 -7
- data/Rakefile +2 -2
- data/UPGRADING.md +19 -2
- data/bench/serializing.rb +7 -0
- data/grape-entity.gemspec +10 -8
- data/lib/grape-entity.rb +2 -0
- data/lib/grape_entity/condition/base.rb +3 -1
- data/lib/grape_entity/condition/block_condition.rb +3 -1
- data/lib/grape_entity/condition/hash_condition.rb +2 -0
- data/lib/grape_entity/condition/symbol_condition.rb +2 -0
- data/lib/grape_entity/condition.rb +20 -11
- data/lib/grape_entity/delegator/base.rb +7 -0
- data/lib/grape_entity/delegator/fetchable_object.rb +2 -0
- data/lib/grape_entity/delegator/hash_object.rb +4 -2
- data/lib/grape_entity/delegator/openstruct_object.rb +2 -0
- data/lib/grape_entity/delegator/plain_object.rb +2 -0
- data/lib/grape_entity/delegator.rb +14 -9
- data/lib/grape_entity/deprecated.rb +13 -0
- data/lib/grape_entity/entity.rb +115 -38
- data/lib/grape_entity/exposure/base.rb +27 -11
- data/lib/grape_entity/exposure/block_exposure.rb +2 -0
- data/lib/grape_entity/exposure/delegator_exposure.rb +2 -0
- data/lib/grape_entity/exposure/formatter_block_exposure.rb +2 -0
- data/lib/grape_entity/exposure/formatter_exposure.rb +2 -0
- data/lib/grape_entity/exposure/nesting_exposure/nested_exposures.rb +27 -15
- data/lib/grape_entity/exposure/nesting_exposure/output_builder.rb +8 -2
- data/lib/grape_entity/exposure/nesting_exposure.rb +36 -30
- data/lib/grape_entity/exposure/represent_exposure.rb +3 -1
- data/lib/grape_entity/exposure.rb +69 -41
- data/lib/grape_entity/options.rb +44 -58
- data/lib/grape_entity/version.rb +3 -1
- data/lib/grape_entity.rb +3 -0
- data/spec/grape_entity/entity_spec.rb +405 -48
- data/spec/grape_entity/exposure/nesting_exposure/nested_exposures_spec.rb +6 -4
- data/spec/grape_entity/exposure/represent_exposure_spec.rb +5 -3
- data/spec/grape_entity/exposure_spec.rb +14 -2
- data/spec/grape_entity/hash_spec.rb +52 -1
- data/spec/grape_entity/options_spec.rb +66 -0
- data/spec/spec_helper.rb +17 -0
- metadata +35 -45
- data/.travis.yml +0 -26
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'grape_entity/exposure/base'
|
2
4
|
require 'grape_entity/exposure/represent_exposure'
|
3
5
|
require 'grape_entity/exposure/block_exposure'
|
@@ -10,67 +12,93 @@ require 'grape_entity/condition'
|
|
10
12
|
module Grape
|
11
13
|
class Entity
|
12
14
|
module Exposure
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
if options[:proc]
|
18
|
-
block_exposure = BlockExposure.new(*base_args, &options[:proc])
|
19
|
-
else
|
20
|
-
delegator_exposure = DelegatorExposure.new(*base_args)
|
21
|
-
end
|
15
|
+
class << self
|
16
|
+
def new(attribute, options)
|
17
|
+
conditions = compile_conditions(attribute, options)
|
18
|
+
base_args = [attribute, options, conditions]
|
22
19
|
|
23
|
-
|
20
|
+
passed_proc = options[:proc]
|
24
21
|
using_class = options[:using]
|
22
|
+
format_with = options[:format_with]
|
25
23
|
|
26
|
-
if
|
27
|
-
|
24
|
+
if using_class
|
25
|
+
build_class_exposure(base_args, using_class, passed_proc)
|
26
|
+
elsif passed_proc
|
27
|
+
build_block_exposure(base_args, passed_proc)
|
28
|
+
elsif format_with
|
29
|
+
build_formatter_exposure(base_args, format_with)
|
30
|
+
elsif options[:nesting]
|
31
|
+
build_nesting_exposure(base_args)
|
28
32
|
else
|
29
|
-
|
33
|
+
build_delegator_exposure(base_args)
|
30
34
|
end
|
35
|
+
end
|
31
36
|
|
32
|
-
|
33
|
-
block_exposure
|
37
|
+
private
|
34
38
|
|
35
|
-
|
36
|
-
|
39
|
+
def compile_conditions(attribute, options)
|
40
|
+
if_conditions = [
|
41
|
+
options[:if_extras],
|
42
|
+
options[:if]
|
43
|
+
].compact.flatten.map { |cond| Condition.new_if(cond) }
|
37
44
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
end
|
45
|
+
unless_conditions = [
|
46
|
+
options[:unless_extras],
|
47
|
+
options[:unless]
|
48
|
+
].compact.flatten.map { |cond| Condition.new_unless(cond) }
|
43
49
|
|
44
|
-
|
45
|
-
NestingExposure.new(*base_args)
|
50
|
+
unless_conditions << expose_nil_condition(attribute, options) if options[:expose_nil] == false
|
46
51
|
|
47
|
-
|
48
|
-
delegator_exposure
|
52
|
+
if_conditions + unless_conditions
|
49
53
|
end
|
50
|
-
end
|
51
54
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
55
|
+
def expose_nil_condition(attribute, options)
|
56
|
+
Condition.new_unless(
|
57
|
+
proc do |object, _options|
|
58
|
+
if options[:proc].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
|
65
|
+
else
|
66
|
+
exec_with_object(options, &options[:proc]).nil?
|
67
|
+
end
|
68
|
+
end
|
69
|
+
)
|
56
70
|
end
|
57
|
-
if_conditions << options[:if] unless options[:if].nil?
|
58
71
|
|
59
|
-
|
60
|
-
|
72
|
+
def build_class_exposure(base_args, using_class, passed_proc)
|
73
|
+
exposure =
|
74
|
+
if passed_proc
|
75
|
+
build_block_exposure(base_args, passed_proc)
|
76
|
+
else
|
77
|
+
build_delegator_exposure(base_args)
|
78
|
+
end
|
79
|
+
|
80
|
+
RepresentExposure.new(*base_args, using_class, exposure)
|
81
|
+
end
|
82
|
+
|
83
|
+
def build_formatter_exposure(base_args, format_with)
|
84
|
+
if format_with.is_a? Symbol
|
85
|
+
FormatterExposure.new(*base_args, format_with)
|
86
|
+
elsif format_with.respond_to?(:call)
|
87
|
+
FormatterBlockExposure.new(*base_args, &format_with)
|
88
|
+
end
|
61
89
|
end
|
62
90
|
|
63
|
-
|
64
|
-
|
65
|
-
unless_conditions.concat(options[:unless_extras])
|
91
|
+
def build_nesting_exposure(base_args)
|
92
|
+
NestingExposure.new(*base_args)
|
66
93
|
end
|
67
|
-
unless_conditions << options[:unless] unless options[:unless].nil?
|
68
94
|
|
69
|
-
|
70
|
-
|
95
|
+
def build_block_exposure(base_args, passed_proc)
|
96
|
+
BlockExposure.new(*base_args, &passed_proc)
|
71
97
|
end
|
72
98
|
|
73
|
-
|
99
|
+
def build_delegator_exposure(base_args)
|
100
|
+
DelegatorExposure.new(*base_args)
|
101
|
+
end
|
74
102
|
end
|
75
103
|
end
|
76
104
|
end
|
data/lib/grape_entity/options.rb
CHANGED
@@ -1,8 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'forwardable'
|
4
|
+
|
1
5
|
module Grape
|
2
6
|
class Entity
|
3
7
|
class Options
|
8
|
+
extend Forwardable
|
9
|
+
|
4
10
|
attr_reader :opts_hash
|
5
11
|
|
12
|
+
def_delegators :opts_hash, :dig, :key?, :fetch, :[], :empty
|
13
|
+
|
6
14
|
def initialize(opts_hash = {})
|
7
15
|
@opts_hash = opts_hash
|
8
16
|
@has_only = !opts_hash[:only].nil?
|
@@ -11,54 +19,33 @@ module Grape
|
|
11
19
|
@should_return_key_cache = {}
|
12
20
|
end
|
13
21
|
|
14
|
-
def
|
15
|
-
|
16
|
-
end
|
22
|
+
def merge(new_opts)
|
23
|
+
return self if new_opts.empty?
|
17
24
|
|
18
|
-
|
19
|
-
|
20
|
-
|
25
|
+
merged = if new_opts.instance_of? Options
|
26
|
+
@opts_hash.merge(new_opts.opts_hash)
|
27
|
+
else
|
28
|
+
@opts_hash.merge(new_opts)
|
29
|
+
end
|
21
30
|
|
22
|
-
|
23
|
-
@opts_hash.key? key
|
24
|
-
end
|
25
|
-
|
26
|
-
def merge(new_opts)
|
27
|
-
if new_opts.empty?
|
28
|
-
self
|
29
|
-
else
|
30
|
-
merged = if new_opts.instance_of? Options
|
31
|
-
@opts_hash.merge(new_opts.opts_hash)
|
32
|
-
else
|
33
|
-
@opts_hash.merge(new_opts)
|
34
|
-
end
|
35
|
-
Options.new(merged)
|
36
|
-
end
|
31
|
+
Options.new(merged)
|
37
32
|
end
|
38
33
|
|
39
34
|
def reverse_merge(new_opts)
|
40
|
-
if new_opts.empty?
|
41
|
-
self
|
42
|
-
else
|
43
|
-
merged = if new_opts.instance_of? Options
|
44
|
-
new_opts.opts_hash.merge(@opts_hash)
|
45
|
-
else
|
46
|
-
new_opts.merge(@opts_hash)
|
47
|
-
end
|
48
|
-
Options.new(merged)
|
49
|
-
end
|
50
|
-
end
|
35
|
+
return self if new_opts.empty?
|
51
36
|
|
52
|
-
|
53
|
-
|
37
|
+
merged = if new_opts.instance_of? Options
|
38
|
+
new_opts.opts_hash.merge(@opts_hash)
|
39
|
+
else
|
40
|
+
new_opts.merge(@opts_hash)
|
41
|
+
end
|
42
|
+
|
43
|
+
Options.new(merged)
|
54
44
|
end
|
55
45
|
|
56
46
|
def ==(other)
|
57
|
-
|
58
|
-
|
59
|
-
else
|
60
|
-
other
|
61
|
-
end
|
47
|
+
other_hash = other.is_a?(Options) ? other.opts_hash : other
|
48
|
+
@opts_hash == other_hash
|
62
49
|
end
|
63
50
|
|
64
51
|
def should_return_key?(key)
|
@@ -66,7 +53,7 @@ module Grape
|
|
66
53
|
|
67
54
|
only = only_fields.nil? ||
|
68
55
|
only_fields.key?(key)
|
69
|
-
except = except_fields
|
56
|
+
except = except_fields&.key?(key) &&
|
70
57
|
except_fields[key] == true
|
71
58
|
only && !except
|
72
59
|
end
|
@@ -96,36 +83,35 @@ module Grape
|
|
96
83
|
end
|
97
84
|
|
98
85
|
def with_attr_path(part)
|
86
|
+
return yield unless part
|
87
|
+
|
99
88
|
stack = (opts_hash[:attr_path] ||= [])
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
result
|
105
|
-
else
|
106
|
-
yield
|
107
|
-
end
|
89
|
+
stack.push part
|
90
|
+
result = yield
|
91
|
+
stack.pop
|
92
|
+
result
|
108
93
|
end
|
109
94
|
|
110
95
|
private
|
111
96
|
|
112
97
|
def build_for_nesting(key)
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
98
|
+
Options.new(
|
99
|
+
opts_hash.dup.reject { |current_key| current_key == :collection }.merge(
|
100
|
+
root: nil,
|
101
|
+
only: only_fields(key),
|
102
|
+
except: except_fields(key),
|
103
|
+
attr_path: opts_hash[:attr_path]
|
104
|
+
)
|
105
|
+
)
|
121
106
|
end
|
122
107
|
|
123
108
|
def build_symbolized_hash(attribute, hash)
|
124
|
-
|
109
|
+
case attribute
|
110
|
+
when Hash
|
125
111
|
attribute.each do |attr, nested_attrs|
|
126
112
|
hash[attr.to_sym] = build_symbolized_hash(nested_attrs, {})
|
127
113
|
end
|
128
|
-
|
114
|
+
when Array
|
129
115
|
return attribute.each { |x| build_symbolized_hash(x, {}) }
|
130
116
|
else
|
131
117
|
hash[attribute.to_sym] = true
|
data/lib/grape_entity/version.rb
CHANGED
data/lib/grape_entity.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_support/version'
|
2
4
|
require 'active_support/core_ext/string/inflections'
|
3
5
|
require 'active_support/core_ext/hash/reverse_merge'
|
@@ -7,3 +9,4 @@ require 'grape_entity/entity'
|
|
7
9
|
require 'grape_entity/delegator'
|
8
10
|
require 'grape_entity/exposure'
|
9
11
|
require 'grape_entity/options'
|
12
|
+
require 'grape_entity/deprecated'
|