rom-repository 1.4.0 → 2.0.0.beta1
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 +14 -6
- data/{LICENSE.txt → LICENSE} +1 -1
- data/README.md +18 -1
- data/lib/rom-repository.rb +1 -2
- data/lib/rom/repository.rb +9 -216
- data/lib/rom/repository/class_interface.rb +16 -33
- data/lib/rom/repository/relation_reader.rb +46 -0
- data/lib/rom/repository/root.rb +3 -59
- data/lib/rom/repository/version.rb +1 -1
- metadata +9 -98
- data/.gitignore +0 -3
- data/.rspec +0 -3
- data/.travis.yml +0 -27
- data/.yardopts +0 -2
- data/Gemfile +0 -38
- data/Rakefile +0 -19
- data/lib/rom/open_struct.rb +0 -35
- data/lib/rom/repository/changeset.rb +0 -155
- data/lib/rom/repository/changeset/associated.rb +0 -100
- data/lib/rom/repository/changeset/create.rb +0 -16
- data/lib/rom/repository/changeset/delete.rb +0 -17
- data/lib/rom/repository/changeset/pipe.rb +0 -97
- data/lib/rom/repository/changeset/restricted.rb +0 -28
- data/lib/rom/repository/changeset/stateful.rb +0 -282
- data/lib/rom/repository/changeset/update.rb +0 -82
- data/lib/rom/repository/command_compiler.rb +0 -257
- data/lib/rom/repository/command_proxy.rb +0 -26
- data/lib/rom/repository/header_builder.rb +0 -65
- data/lib/rom/repository/mapper_builder.rb +0 -23
- data/lib/rom/repository/relation_proxy.rb +0 -337
- data/lib/rom/repository/relation_proxy/combine.rb +0 -320
- data/lib/rom/repository/relation_proxy/wrap.rb +0 -78
- data/lib/rom/repository/struct_builder.rb +0 -83
- data/lib/rom/struct.rb +0 -113
- data/log/.gitkeep +0 -0
- data/rom-repository.gemspec +0 -23
- data/spec/integration/changeset_spec.rb +0 -193
- data/spec/integration/command_macros_spec.rb +0 -191
- data/spec/integration/command_spec.rb +0 -228
- data/spec/integration/multi_adapter_spec.rb +0 -73
- data/spec/integration/repository/aggregate_spec.rb +0 -58
- data/spec/integration/repository_spec.rb +0 -406
- data/spec/integration/root_repository_spec.rb +0 -106
- data/spec/integration/typed_structs_spec.rb +0 -64
- data/spec/shared/database.rb +0 -79
- data/spec/shared/mappers.rb +0 -35
- data/spec/shared/models.rb +0 -41
- data/spec/shared/plugins.rb +0 -66
- data/spec/shared/relations.rb +0 -115
- data/spec/shared/repo.rb +0 -86
- data/spec/shared/seeds.rb +0 -30
- data/spec/shared/structs.rb +0 -140
- data/spec/spec_helper.rb +0 -83
- data/spec/support/mapper_registry.rb +0 -9
- data/spec/support/mutant.rb +0 -10
- data/spec/unit/changeset/associate_spec.rb +0 -120
- data/spec/unit/changeset/map_spec.rb +0 -111
- data/spec/unit/changeset_spec.rb +0 -186
- data/spec/unit/relation_proxy_spec.rb +0 -202
- data/spec/unit/repository/changeset_spec.rb +0 -197
- data/spec/unit/repository/inspect_spec.rb +0 -18
- data/spec/unit/repository/session_spec.rb +0 -251
- data/spec/unit/repository/transaction_spec.rb +0 -42
- data/spec/unit/session_spec.rb +0 -46
- data/spec/unit/struct_builder_spec.rb +0 -128
@@ -1,100 +0,0 @@
|
|
1
|
-
require 'rom/initializer'
|
2
|
-
|
3
|
-
module ROM
|
4
|
-
class Changeset
|
5
|
-
# Associated changesets automatically set up FKs
|
6
|
-
#
|
7
|
-
# @api public
|
8
|
-
class Associated
|
9
|
-
extend Initializer
|
10
|
-
|
11
|
-
# @!attribute [r] left
|
12
|
-
# @return [Changeset::Create] Child changeset
|
13
|
-
param :left
|
14
|
-
|
15
|
-
# @!attribute [r] associations
|
16
|
-
# @return [Array] List of association identifiers from relation schema
|
17
|
-
option :associations
|
18
|
-
|
19
|
-
# Infer association name from an object with a schema
|
20
|
-
#
|
21
|
-
# This expects other to be an object with a schema that includes a primary key
|
22
|
-
# attribute with :source meta information. This makes it work with both structs
|
23
|
-
# and relations
|
24
|
-
#
|
25
|
-
# @see Stateful#associate
|
26
|
-
#
|
27
|
-
# @api private
|
28
|
-
def self.infer_assoc_name(other)
|
29
|
-
schema = other.class.schema
|
30
|
-
attrs = schema.is_a?(Hash) ? schema.values : schema
|
31
|
-
pk = attrs.detect { |attr| attr.meta[:primary_key] }
|
32
|
-
|
33
|
-
if pk
|
34
|
-
pk.meta[:source].relation
|
35
|
-
else
|
36
|
-
raise ArgumentError, "can't infer association name for #{other}"
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
# Commit changeset's composite command
|
41
|
-
#
|
42
|
-
# @example
|
43
|
-
# task_changeset = task_repo.
|
44
|
-
# changeset(title: 'Task One').
|
45
|
-
# associate(user, :user).
|
46
|
-
# commit
|
47
|
-
# # {:id => 1, :user_id => 1, title: 'Task One'}
|
48
|
-
#
|
49
|
-
# @return [Array<Hash>, Hash]
|
50
|
-
#
|
51
|
-
# @api public
|
52
|
-
def commit
|
53
|
-
command.call
|
54
|
-
end
|
55
|
-
|
56
|
-
# @api public
|
57
|
-
def associate(other, name = Associated.infer_assoc_name(other))
|
58
|
-
self.class.new(left, associations: associations.merge(name => other))
|
59
|
-
end
|
60
|
-
|
61
|
-
# Create a composed command
|
62
|
-
#
|
63
|
-
# @example using existing parent data
|
64
|
-
# user_changeset = user_repo.changeset(name: 'Jane')
|
65
|
-
# task_changeset = task_repo.changeset(title: 'Task One')
|
66
|
-
#
|
67
|
-
# user = user_repo.create(user_changeset)
|
68
|
-
# task = task_repo.create(task_changeset.associate(user, :user))
|
69
|
-
#
|
70
|
-
# @example saving both parent and child in one go
|
71
|
-
# user_changeset = user_repo.changeset(name: 'Jane')
|
72
|
-
# task_changeset = task_repo.changeset(title: 'Task One')
|
73
|
-
#
|
74
|
-
# task = task_repo.create(task_changeset.associate(user, :user))
|
75
|
-
#
|
76
|
-
# This works *only* with parent => child(ren) changeset hierarchy
|
77
|
-
#
|
78
|
-
# @return [ROM::Command::Composite]
|
79
|
-
#
|
80
|
-
# @api public
|
81
|
-
def command
|
82
|
-
associations.reduce(left.command.curry(left)) do |a, (assoc, other)|
|
83
|
-
case other
|
84
|
-
when Changeset
|
85
|
-
a >> other.command.with_association(assoc).curry(other)
|
86
|
-
when Associated
|
87
|
-
a >> other.command.with_association(assoc)
|
88
|
-
else
|
89
|
-
a.with_association(assoc, parent: other)
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
# @api private
|
95
|
-
def relation
|
96
|
-
left.relation
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
require 'rom/repository/changeset/restricted'
|
2
|
-
|
3
|
-
module ROM
|
4
|
-
class Changeset
|
5
|
-
# Changeset specialization for delete commands
|
6
|
-
#
|
7
|
-
# Delete changesets will execute delete command for its relation, which
|
8
|
-
# means proper restricted relations should be used with this changeset.
|
9
|
-
#
|
10
|
-
# @api public
|
11
|
-
class Delete < Changeset
|
12
|
-
include Restricted
|
13
|
-
|
14
|
-
command_type :delete
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,97 +0,0 @@
|
|
1
|
-
require 'transproc/registry'
|
2
|
-
require 'transproc/transformer'
|
3
|
-
|
4
|
-
module ROM
|
5
|
-
class Changeset
|
6
|
-
# Transproc Registry useful for pipe
|
7
|
-
#
|
8
|
-
# @api private
|
9
|
-
module PipeRegistry
|
10
|
-
extend Transproc::Registry
|
11
|
-
|
12
|
-
import Transproc::HashTransformations
|
13
|
-
|
14
|
-
def self.add_timestamps(data)
|
15
|
-
now = Time.now
|
16
|
-
data.merge(created_at: now, updated_at: now)
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.touch(data)
|
20
|
-
data.merge(updated_at: Time.now)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
# Composable data transformation pipe used by default in changesets
|
25
|
-
#
|
26
|
-
# @api private
|
27
|
-
class Pipe < Transproc::Transformer[PipeRegistry]
|
28
|
-
extend Initializer
|
29
|
-
|
30
|
-
param :processor, default: -> { self.class.transproc }
|
31
|
-
option :use_for_diff, optional: true, default: -> { true }
|
32
|
-
option :diff_processor, optional: true, default: -> { use_for_diff ? processor : nil }
|
33
|
-
|
34
|
-
def self.[](name)
|
35
|
-
container[name]
|
36
|
-
end
|
37
|
-
|
38
|
-
def [](name)
|
39
|
-
self.class[name]
|
40
|
-
end
|
41
|
-
|
42
|
-
def bind(context)
|
43
|
-
return self unless processor.is_a?(Proc) || diff_processor.is_a?(Proc)
|
44
|
-
|
45
|
-
new(bind_processor(processor, context), diff_processor: bind_processor(diff_processor, context))
|
46
|
-
end
|
47
|
-
|
48
|
-
def compose(other, use_for_diff: other.is_a?(Pipe) ? other.use_for_diff : false)
|
49
|
-
new_proc = processor ? processor >> other : other
|
50
|
-
|
51
|
-
if use_for_diff
|
52
|
-
diff_proc = diff_processor ? diff_processor >> other : other
|
53
|
-
new(new_proc, diff_processor: diff_proc)
|
54
|
-
else
|
55
|
-
new(new_proc)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
alias_method :>>, :compose
|
59
|
-
|
60
|
-
def call(data)
|
61
|
-
if processor
|
62
|
-
processor.call(data)
|
63
|
-
else
|
64
|
-
data
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def for_diff(data)
|
69
|
-
if diff_processor
|
70
|
-
diff_processor.call(data)
|
71
|
-
else
|
72
|
-
data
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def with(opts)
|
77
|
-
if opts.empty?
|
78
|
-
self
|
79
|
-
else
|
80
|
-
Pipe.new(processor, options.merge(opts))
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
def new(processor, opts = EMPTY_HASH)
|
85
|
-
Pipe.new(processor, options.merge(opts))
|
86
|
-
end
|
87
|
-
|
88
|
-
def bind_processor(processor, context)
|
89
|
-
if processor.is_a?(Proc)
|
90
|
-
self[-> *args { context.instance_exec(*args, &processor) }]
|
91
|
-
else
|
92
|
-
processor
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
module ROM
|
2
|
-
class Changeset
|
3
|
-
module Restricted
|
4
|
-
# Return a command restricted by the changeset's relation
|
5
|
-
#
|
6
|
-
# @see Changeset#command
|
7
|
-
#
|
8
|
-
# @api private
|
9
|
-
def command
|
10
|
-
super.new(relation)
|
11
|
-
end
|
12
|
-
|
13
|
-
# Restrict changeset's relation by its PK
|
14
|
-
#
|
15
|
-
# @example
|
16
|
-
# repo.changeset(UpdateUser).by_pk(1).data(name: "Jane")
|
17
|
-
#
|
18
|
-
# @param [Object] pk
|
19
|
-
#
|
20
|
-
# @return [Changeset]
|
21
|
-
#
|
22
|
-
# @api public
|
23
|
-
def by_pk(pk, data = EMPTY_HASH)
|
24
|
-
new(relation.by_pk(pk), __data__: data)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
@@ -1,282 +0,0 @@
|
|
1
|
-
require 'rom/repository/changeset/pipe'
|
2
|
-
|
3
|
-
module ROM
|
4
|
-
class Changeset
|
5
|
-
# Stateful changesets carry data and can transform it into
|
6
|
-
# a different structure compatible with a persistence backend
|
7
|
-
#
|
8
|
-
# @abstract
|
9
|
-
class Stateful < Changeset
|
10
|
-
# Default no-op pipe
|
11
|
-
EMPTY_PIPE = Pipe.new.freeze
|
12
|
-
|
13
|
-
# @!attribute [r] __data__
|
14
|
-
# @return [Hash] The relation data
|
15
|
-
# @api private
|
16
|
-
option :__data__, optional: true
|
17
|
-
|
18
|
-
# @!attribute [r] pipe
|
19
|
-
# @return [Changeset::Pipe] data transformation pipe
|
20
|
-
# @api private
|
21
|
-
option :pipe, reader: false, optional: true
|
22
|
-
|
23
|
-
# Define a changeset mapping
|
24
|
-
#
|
25
|
-
# Subsequent mapping definitions will be composed together
|
26
|
-
# and applied in the order they way defined
|
27
|
-
#
|
28
|
-
# @example Transformation DSL
|
29
|
-
# class NewUser < ROM::Changeset::Create
|
30
|
-
# map do
|
31
|
-
# unwrap :address, prefix: true
|
32
|
-
# end
|
33
|
-
# end
|
34
|
-
#
|
35
|
-
# @example Using custom block
|
36
|
-
# class NewUser < ROM::Changeset::Create
|
37
|
-
# map do |tuple|
|
38
|
-
# tuple.merge(created_at: Time.now)
|
39
|
-
# end
|
40
|
-
# end
|
41
|
-
#
|
42
|
-
# @example Multiple mappings (executed in the order of definition)
|
43
|
-
# class NewUser < ROM::Changeset::Create
|
44
|
-
# map do
|
45
|
-
# unwrap :address, prefix: true
|
46
|
-
# end
|
47
|
-
#
|
48
|
-
# map do |tuple|
|
49
|
-
# tuple.merge(created_at: Time.now)
|
50
|
-
# end
|
51
|
-
# end
|
52
|
-
#
|
53
|
-
# @return [Array<Pipe>, Transproc::Function>]
|
54
|
-
#
|
55
|
-
# @see https://github.com/solnic/transproc Transproc
|
56
|
-
#
|
57
|
-
# @api public
|
58
|
-
def self.map(options = EMPTY_HASH, &block)
|
59
|
-
if block.parameters.empty?
|
60
|
-
pipes << Class.new(Pipe, &block).new(options)
|
61
|
-
else
|
62
|
-
pipes << Pipe.new(block, options)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
# Define a changeset mapping excluded from diffs
|
67
|
-
#
|
68
|
-
# @see Changeset::Stateful.map
|
69
|
-
# @see Changeset::Stateful#extend
|
70
|
-
#
|
71
|
-
# @return [Array<Pipe>, Transproc::Function>]
|
72
|
-
#
|
73
|
-
# @api public
|
74
|
-
def self.extend(*, &block)
|
75
|
-
if block
|
76
|
-
map(use_for_diff: false, &block)
|
77
|
-
else
|
78
|
-
super
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
# Build default pipe object
|
83
|
-
#
|
84
|
-
# This can be overridden in a custom changeset subclass
|
85
|
-
#
|
86
|
-
# @return [Pipe]
|
87
|
-
def self.default_pipe(context)
|
88
|
-
pipes.size > 0 ? pipes.map { |p| p.bind(context) }.reduce(:>>) : EMPTY_PIPE
|
89
|
-
end
|
90
|
-
|
91
|
-
# @api private
|
92
|
-
def self.inherited(klass)
|
93
|
-
return if klass == ROM::Changeset
|
94
|
-
super
|
95
|
-
klass.instance_variable_set(:@__pipes__, pipes ? pipes.dup : EMPTY_ARRAY)
|
96
|
-
end
|
97
|
-
|
98
|
-
# @api private
|
99
|
-
def self.pipes
|
100
|
-
@__pipes__
|
101
|
-
end
|
102
|
-
|
103
|
-
# Pipe changeset's data using custom steps define on the pipe
|
104
|
-
#
|
105
|
-
# @overload map(*steps)
|
106
|
-
# Apply mapping using built-in transformations
|
107
|
-
#
|
108
|
-
# @example
|
109
|
-
# changeset.map(:add_timestamps)
|
110
|
-
#
|
111
|
-
# @param [Array<Symbol>] steps A list of mapping steps
|
112
|
-
#
|
113
|
-
# @overload map(&block)
|
114
|
-
# Apply mapping using a custom block
|
115
|
-
#
|
116
|
-
# @example
|
117
|
-
# changeset.map { |tuple| tuple.merge(created_at: Time.now) }
|
118
|
-
#
|
119
|
-
# @overload map(*steps, &block)
|
120
|
-
# Apply mapping using built-in transformations and a custom block
|
121
|
-
#
|
122
|
-
# @example
|
123
|
-
# changeset.map(:add_timestamps) { |tuple| tuple.merge(status: 'published') }
|
124
|
-
#
|
125
|
-
# @param [Array<Symbol>] steps A list of mapping steps
|
126
|
-
#
|
127
|
-
# @return [Changeset]
|
128
|
-
#
|
129
|
-
# @api public
|
130
|
-
def map(*steps, &block)
|
131
|
-
extend(*steps, use_for_diff: true, &block)
|
132
|
-
end
|
133
|
-
|
134
|
-
# Pipe changeset's data using custom steps define on the pipe.
|
135
|
-
# You should use #map instead except updating timestamp fields.
|
136
|
-
# Calling changeset.extend builds a pipe that excludes certain
|
137
|
-
# steps for generating the diff. Currently the only place where
|
138
|
-
# it is used is update changesets with the `:touch` step, i.e.
|
139
|
-
# `changeset.extend(:touch).diff` will exclude `:updated_at`
|
140
|
-
# from the diff.
|
141
|
-
#
|
142
|
-
# @see Changeset::Stateful#map
|
143
|
-
#
|
144
|
-
# @return [Changeset]
|
145
|
-
#
|
146
|
-
# @api public
|
147
|
-
def extend(*steps, use_for_diff: false, **opts, &block)
|
148
|
-
options = { use_for_diff: use_for_diff, **opts }
|
149
|
-
|
150
|
-
if block
|
151
|
-
if steps.size > 0
|
152
|
-
extend(*steps, options).extend(options, &block)
|
153
|
-
else
|
154
|
-
with(pipe: pipe.compose(Pipe.new(block).bind(self), options))
|
155
|
-
end
|
156
|
-
else
|
157
|
-
with(pipe: steps.reduce(pipe.with(options)) { |a, e| a.compose(pipe[e], options) })
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
# Return changeset with data
|
162
|
-
#
|
163
|
-
# @param [Hash] data
|
164
|
-
#
|
165
|
-
# @return [Changeset]
|
166
|
-
#
|
167
|
-
# @api public
|
168
|
-
def data(data)
|
169
|
-
with(__data__: data)
|
170
|
-
end
|
171
|
-
|
172
|
-
# Coerce changeset to a hash
|
173
|
-
#
|
174
|
-
# This will send the data through the pipe
|
175
|
-
#
|
176
|
-
# @return [Hash]
|
177
|
-
#
|
178
|
-
# @api public
|
179
|
-
def to_h
|
180
|
-
pipe.call(__data__)
|
181
|
-
end
|
182
|
-
alias_method :to_hash, :to_h
|
183
|
-
|
184
|
-
# Coerce changeset to an array
|
185
|
-
#
|
186
|
-
# This will send the data through the pipe
|
187
|
-
#
|
188
|
-
# @return [Array]
|
189
|
-
#
|
190
|
-
# @api public
|
191
|
-
def to_a
|
192
|
-
result == :one ? [to_h] : __data__.map { |element| pipe.call(element) }
|
193
|
-
end
|
194
|
-
alias_method :to_ary, :to_a
|
195
|
-
|
196
|
-
# Commit stateful changeset
|
197
|
-
#
|
198
|
-
# @see Changeset#commit
|
199
|
-
#
|
200
|
-
# @api public
|
201
|
-
def commit
|
202
|
-
command.call(self)
|
203
|
-
end
|
204
|
-
|
205
|
-
# Associate a changeset with another changeset or hash-like object
|
206
|
-
#
|
207
|
-
# @example with another changeset
|
208
|
-
# new_user = user_repo.changeset(name: 'Jane')
|
209
|
-
# new_task = user_repo.changeset(:tasks, title: 'A task')
|
210
|
-
#
|
211
|
-
# new_task.associate(new_user, :users)
|
212
|
-
#
|
213
|
-
# @example with a hash-like object
|
214
|
-
# user = user_repo.users.by_pk(1).one
|
215
|
-
# new_task = user_repo.changeset(:tasks, title: 'A task')
|
216
|
-
#
|
217
|
-
# new_task.associate(user, :users)
|
218
|
-
#
|
219
|
-
# @param [#to_hash, Changeset] other Other changeset or hash-like object
|
220
|
-
# @param [Symbol] assoc The association identifier from schema
|
221
|
-
#
|
222
|
-
# @api public
|
223
|
-
def associate(other, name = Associated.infer_assoc_name(other))
|
224
|
-
Associated.new(self, associations: { name => other })
|
225
|
-
end
|
226
|
-
|
227
|
-
# Return command result type
|
228
|
-
#
|
229
|
-
# @return [Symbol]
|
230
|
-
#
|
231
|
-
# @api private
|
232
|
-
def result
|
233
|
-
__data__.is_a?(Array) ? :many : :one
|
234
|
-
end
|
235
|
-
|
236
|
-
# @api public
|
237
|
-
def command
|
238
|
-
command_compiler.(command_type, relation_identifier, DEFAULT_COMMAND_OPTS.merge(result: result))
|
239
|
-
end
|
240
|
-
|
241
|
-
# Return string representation of the changeset
|
242
|
-
#
|
243
|
-
# @return [String]
|
244
|
-
#
|
245
|
-
# @api public
|
246
|
-
def inspect
|
247
|
-
%(#<#{self.class} relation=#{relation.name.inspect} data=#{__data__}>)
|
248
|
-
end
|
249
|
-
|
250
|
-
# Data transformation pipe
|
251
|
-
#
|
252
|
-
# @return [Changeset::Pipe]
|
253
|
-
#
|
254
|
-
# @api private
|
255
|
-
def pipe
|
256
|
-
@pipe ||= self.class.default_pipe(self)
|
257
|
-
end
|
258
|
-
|
259
|
-
private
|
260
|
-
|
261
|
-
# @api private
|
262
|
-
def respond_to_missing?(meth, include_private = false)
|
263
|
-
super || __data__.respond_to?(meth)
|
264
|
-
end
|
265
|
-
|
266
|
-
# @api private
|
267
|
-
def method_missing(meth, *args, &block)
|
268
|
-
if __data__.respond_to?(meth)
|
269
|
-
response = __data__.__send__(meth, *args, &block)
|
270
|
-
|
271
|
-
if response.is_a?(__data__.class)
|
272
|
-
with(__data__: response)
|
273
|
-
else
|
274
|
-
response
|
275
|
-
end
|
276
|
-
else
|
277
|
-
super
|
278
|
-
end
|
279
|
-
end
|
280
|
-
end
|
281
|
-
end
|
282
|
-
end
|