levee 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/levee/adapters/json_api.rb +36 -0
- data/lib/levee/builder.rb +71 -10
- data/lib/levee/validator.rb +3 -2
- data/lib/levee/version.rb +1 -1
- metadata +3 -3
- data/levee-0.0.2.gem +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7c93ba9e7e4b2dd04833b04ae1ece0d87a8fd349
|
4
|
+
data.tar.gz: d17711b6b67052cb693b9c34890d3da4feaa0b26
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 64e427d6f9d8a2d16cd6e9168139a68e49e56e582fbb01309e5ac7ac446989a12f5c29570af79ded87eae6a1d504eb7b184ca94ece50accdcf667c1d461b17c7
|
7
|
+
data.tar.gz: 9d53286d208e26ff64c38d6e330cb11e7500bb13c18c989f1ab45c1b50daf4e229280335a93ff30c348c08209460d744e12dd7fc144a2c534737b9611bebcc5f
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module JsonApi
|
2
|
+
|
3
|
+
def included
|
4
|
+
@included
|
5
|
+
end
|
6
|
+
|
7
|
+
def included=(v)
|
8
|
+
@included = v
|
9
|
+
end
|
10
|
+
|
11
|
+
def set_params_using_adapter(params)
|
12
|
+
self.params = params[:data]
|
13
|
+
self.included = params[:included]
|
14
|
+
validate_params
|
15
|
+
validate_included
|
16
|
+
end
|
17
|
+
|
18
|
+
def validate_params
|
19
|
+
message = "Params passed to a builder using :json_api adapter must be a hash with the root_node data"
|
20
|
+
raise message unless params.respond_to?(:fetch)
|
21
|
+
return true if params.is_a? Array
|
22
|
+
message = "Params passed to builder must not have a root node"
|
23
|
+
key = params.keys.first
|
24
|
+
raise message if key && key.to_s.camelize == object_class.to_s
|
25
|
+
end
|
26
|
+
|
27
|
+
def validate_included
|
28
|
+
message = "Params passed to builder must be a hash"
|
29
|
+
raise message unless params.respond_to?(:fetch)
|
30
|
+
return true if params.is_a? Array
|
31
|
+
message = "Params passed to builder must not have a root node"
|
32
|
+
key = params.keys.first
|
33
|
+
raise message if key && key.to_s.camelize == object_class.to_s
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
data/lib/levee/builder.rb
CHANGED
@@ -10,8 +10,7 @@ module Levee
|
|
10
10
|
:builder_options
|
11
11
|
|
12
12
|
def initialize(params, options={}, &blk)
|
13
|
-
|
14
|
-
validate_params
|
13
|
+
set_params_using_adapter(params)
|
15
14
|
self.errors = []
|
16
15
|
self.nested_objects_to_save = []
|
17
16
|
self.permitted_attributes = [:id]
|
@@ -24,6 +23,7 @@ module Levee
|
|
24
23
|
unless params.is_a? Array
|
25
24
|
self.object = object_class.find_by(id: params[:id]) || object_class.new
|
26
25
|
end
|
26
|
+
Rails.logger.debug({message: "#{self.class} building object", object: object, parmas: params })
|
27
27
|
assign_parameters_in_transaction
|
28
28
|
end
|
29
29
|
|
@@ -54,6 +54,10 @@ module Levee
|
|
54
54
|
begin
|
55
55
|
perform_in_transaction
|
56
56
|
rescue => e
|
57
|
+
Rails.logger.warn({message: "Error caught in builder",
|
58
|
+
error: e,
|
59
|
+
builder: self,
|
60
|
+
params: params})
|
57
61
|
raise_error = -> { raise e }
|
58
62
|
rescue_errors(e) || raise_error.call
|
59
63
|
ensure
|
@@ -61,15 +65,16 @@ module Levee
|
|
61
65
|
raise ActiveRecord::Rollback unless errors.flatten.empty?
|
62
66
|
end
|
63
67
|
end
|
64
|
-
Rails.logger.
|
65
|
-
|
66
|
-
self.object = object.reload if errors.empty? && object.try(:persisted?)
|
68
|
+
Rails.logger.warn({message: "Builder Errors",
|
69
|
+
errors: errors})
|
70
|
+
# self.object = object.reload if errors.empty? && object.try(:persisted?)
|
67
71
|
errors.empty? ? object : {errors: errors, error_status: errors.first[:status]}
|
68
72
|
end
|
69
73
|
|
70
74
|
def perform_in_transaction
|
71
|
-
self.errors += validator.validate_params.errors if validator
|
75
|
+
self.errors += validator.validate_params(builder_options).errors if validator
|
72
76
|
return false if errors.any?
|
77
|
+
flatten_attributes
|
73
78
|
self.object = top_level_array || call_setter_for_each_param_key
|
74
79
|
return true unless requires_save && !top_level_array
|
75
80
|
before_save_callbacks.each { |callback| send(callback) }
|
@@ -80,6 +85,7 @@ module Levee
|
|
80
85
|
end
|
81
86
|
|
82
87
|
def call_setter_for_each_param_key
|
88
|
+
Rails.logger.info({message: "Attributes being set:", attributes: params})
|
83
89
|
params.each do |key, value|
|
84
90
|
send_if_key_included_in_attributes(key.to_sym, value)
|
85
91
|
end
|
@@ -90,7 +96,11 @@ module Levee
|
|
90
96
|
if permitted_attributes.include?(key)
|
91
97
|
self.send(key, value)
|
92
98
|
else
|
93
|
-
|
99
|
+
error = {status: 400, message: "Unpermitted parameter key #{key}"}
|
100
|
+
errors << error
|
101
|
+
Rails.logger.warn({message: "Unpermitted parameter key, not listed in #{self.class} attributes",
|
102
|
+
key: key,
|
103
|
+
listed_attributes: permitted_attributes})
|
94
104
|
raise ActiveRecord::Rollback
|
95
105
|
end
|
96
106
|
end
|
@@ -110,6 +120,10 @@ module Levee
|
|
110
120
|
rescue => e
|
111
121
|
if params.has_key?(method_name)
|
112
122
|
message = "Unable to process value for :#{method_name}, no attribute writer. Be sure to override the automatic setters for all params that do not map straight to a model attribute."
|
123
|
+
Rails.logger.warn({message: message,
|
124
|
+
missing_writer: method_name,
|
125
|
+
value: args.first,
|
126
|
+
error: error})
|
113
127
|
self.errors << {status: 422, message: message}
|
114
128
|
else
|
115
129
|
raise e
|
@@ -146,7 +160,10 @@ module Levee
|
|
146
160
|
|
147
161
|
def raise_if_validation_error(rescued_error)
|
148
162
|
if rescued_error.is_a? ActiveRecord::RecordInvalid
|
149
|
-
|
163
|
+
error = { status: 422, code: 'validation_error', message: rescued_error.message, full_messages: object.errors.full_messages, record: rescued_error.record, error: rescued_error }
|
164
|
+
Rails.logger.warn error
|
165
|
+
self.errors << error
|
166
|
+
Rails.warn "Transaction rolled back"
|
150
167
|
raise ActiveRecord::Rollback
|
151
168
|
end
|
152
169
|
end
|
@@ -154,14 +171,20 @@ module Levee
|
|
154
171
|
def raise_if_argument_error(rescued_error)
|
155
172
|
if rescued_error.is_a? ArgumentError
|
156
173
|
message = "All methods on the builder that override attribute setters must accept one argument to catch the parameter value"
|
157
|
-
|
174
|
+
error = { status: 500, code: 'builder_error', message: message, error: rescued_error }
|
175
|
+
Rails.logger.error error
|
176
|
+
self.errors << error
|
177
|
+
Rails.warn "Transaction rolled back"
|
158
178
|
raise ArgumentError.new message
|
159
179
|
end
|
160
180
|
end
|
161
181
|
|
162
182
|
def raise_if_unknown_attribute_error(rescued_error)
|
163
183
|
if rescued_error.is_a? ActiveRecord::UnknownAttributeError
|
164
|
-
|
184
|
+
error = { status: 400, code: 'unknown_attribute_error', message: rescued_error.message, record: rescued_error.record, error: rescued_error, trace: rescued_error.backtrace }
|
185
|
+
Rails.logger.warn error
|
186
|
+
self.errors << error
|
187
|
+
Rails.warn "Transaction rolled back"
|
165
188
|
raise ActiveRecord::Rollback
|
166
189
|
end
|
167
190
|
end
|
@@ -177,11 +200,13 @@ module Levee
|
|
177
200
|
|
178
201
|
def validate_params
|
179
202
|
message = "Params passed to builder must be a hash or top level array"
|
203
|
+
# Rails.logger.error message
|
180
204
|
raise message unless params.respond_to?(:fetch)
|
181
205
|
return true if params.is_a? Array
|
182
206
|
message = "Params passed to builder must not have a root node"
|
183
207
|
key = params.keys.first
|
184
208
|
raise message if key && key.to_s.camelize == object_class.to_s
|
209
|
+
Rails.logger.debug({message: "Params passed validation", builder: "self.class", params: params})
|
185
210
|
end
|
186
211
|
|
187
212
|
#used so that id setter is not called by default
|
@@ -226,5 +251,41 @@ module Levee
|
|
226
251
|
def self._validator
|
227
252
|
@validator
|
228
253
|
end
|
254
|
+
|
255
|
+
def self.set_adapter(adapter)
|
256
|
+
adapter_module = adapter.to_s.camelize.constantize
|
257
|
+
self.include adapter_module
|
258
|
+
self.extend adapter_module
|
259
|
+
end
|
260
|
+
|
261
|
+
def set_params_using_adapter(params)
|
262
|
+
self.params = params
|
263
|
+
validate_params
|
264
|
+
end
|
265
|
+
|
266
|
+
def flatten_attributes
|
267
|
+
if params.is_a?(Hash)
|
268
|
+
self.params = flatten_hash(params)
|
269
|
+
elsif params.is_a?(Array)
|
270
|
+
self.params = flatten_array
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
def flatten_array
|
275
|
+
params.map do |p|
|
276
|
+
flatten_hash(p)
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
def flatten_hash(val)
|
281
|
+
if val.fetch(:attributes, nil)
|
282
|
+
p = val.dup
|
283
|
+
p[:attributes][:id] = val[:id] if val[:id]
|
284
|
+
p[:attributes][:type] = val[:type] if val[:type]
|
285
|
+
p[:attributes]
|
286
|
+
else
|
287
|
+
val
|
288
|
+
end
|
289
|
+
end
|
229
290
|
end
|
230
291
|
end
|
data/lib/levee/validator.rb
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
module Levee
|
2
2
|
class Validator
|
3
|
-
attr_accessor :errors, :params
|
3
|
+
attr_accessor :errors, :params, :builder_options
|
4
4
|
|
5
5
|
def initialize(params)
|
6
6
|
self.errors = []
|
7
7
|
self.params = params
|
8
8
|
end
|
9
9
|
|
10
|
-
def validate_params
|
10
|
+
def validate_params(builder_options = {})
|
11
|
+
@builder_options = builder_options
|
11
12
|
validations.each { |val| send(val) }
|
12
13
|
self
|
13
14
|
end
|
data/lib/levee/version.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Levee
|
2
2
|
extend self
|
3
3
|
|
4
|
-
VERSION = "0.0.
|
4
|
+
VERSION = "0.0.4"
|
5
5
|
|
6
6
|
def gem_description
|
7
7
|
%Q(The purpose of the builder object is to create a layer of abstraction between the controller and models in a Rails application. The builder is particularly useful for receiving complex post and put requests with multiple parameters, but is lightweight enough to use for simple writes when some filtering or parameter combination validation might be useful before writing to the database. Since it wraps the entire write action to mulitple models in a single transaction, any failure in the builder will result in the entire request being rolled back.)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: levee
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Martinson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-07-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -70,9 +70,9 @@ files:
|
|
70
70
|
- LICENSE.txt
|
71
71
|
- README.md
|
72
72
|
- Rakefile
|
73
|
-
- levee-0.0.2.gem
|
74
73
|
- levee.gemspec
|
75
74
|
- lib/levee.rb
|
75
|
+
- lib/levee/adapters/json_api.rb
|
76
76
|
- lib/levee/builder.rb
|
77
77
|
- lib/levee/validator.rb
|
78
78
|
- lib/levee/version.rb
|
data/levee-0.0.2.gem
DELETED
Binary file
|