lev 4.0.0 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NmIyODE2NzY1ZTAwZjA4YzZmY2NmYzYyNzFiZmVmOGJhMWE4MzNkYw==
5
+ data.tar.gz: !binary |-
6
+ MWE4YzcxOWFkYmU2ZTQ5ZjllMDg0MWQ3NTdkZTVhNjZjYjFjZWUzMA==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ ZTExN2U3Njg2MmM2OTQ0NTk0NDZmYjk2NDU4NmE1NjBmOTIwNDJlMzY3MGRk
10
+ MTc5NmRiMjJhNTljMjc3Yzg2OGE2NmU1Y2IwMDQ1ZDlkYTA4MjI4N2QzODA0
11
+ NzZlMGMyYWYzMzEyM2QyM2UyN2EzY2NlN2FjYjdlMjQyYWU0NjA=
12
+ data.tar.gz: !binary |-
13
+ MzA2YjM3ZTRiOWRlNzJiZWNjZDRhZWE5NWU1MjI5OGQ0OWZhMDdlZmJkNjFi
14
+ ZTE5YWRlNjljNDE4NTQ2ZWU3OTIzN2FhZTYyZGM2ODk0N2MyZjBkOGZhODRh
15
+ NzJhNTk5NDUyYjk3MGE0NGZkYTM0OGViNDA4MTA4MmNhNzhjYjM=
data/README.md CHANGED
@@ -17,7 +17,7 @@ Lev introduces two main constructs to get around these issues: **Routines** and
17
17
 
18
18
  ## Routines
19
19
 
20
- Lev's Routines are pieces of code that have all the responsibility for making one thing (one use case) happen, e.g. "add an email to a user", "register a student to a class", etc), normally acting on objects from more than one model.
20
+ Lev's Routines are pieces of code that have all the responsibility for making one thing (one use case) happen, e.g. "add an email to a user", "register a student to a class", etc), normally acting on objects from more than one model.
21
21
 
22
22
  Routines...
23
23
 
@@ -30,12 +30,12 @@ In an OO/MVC world, an operation that involves multiple objects might be impleme
30
30
  Routines typically don't have any persistent state that is used over and over again; they are created, used, and forgotten. A routine is a glorified function with a special single-responsibility purpose.
31
31
 
32
32
  A class becomes a routine by calling `lev_routine` in its definition, e.g.:
33
-
33
+
34
34
  class MyRoutine
35
- lev_routine
35
+ lev_routine
36
36
  ...
37
37
 
38
- Other than that, all a routine has to do is implement an "exec" method (typically `protected`) that takes arbitrary arguments and that adds errors to an internal array-like "errors" object and outputs to a "outputs" hash. Two convenience methods are provided for adding errors:
38
+ Other than that, all a routine has to do is implement an "exec" method (typically `protected`) that takes arbitrary arguments and that adds errors to an internal array-like "errors" object and outputs to a "outputs" hash. Two convenience methods are provided for adding errors:
39
39
 
40
40
  Errors can be recorded in a number of ways. You can manually add errors to the built-in `errors` object:
41
41
 
@@ -62,7 +62,7 @@ Here's an example setting an error and an output:
62
62
  outputs[:bar] = foo * 2
63
63
  end
64
64
  end
65
-
65
+
66
66
  Additionally, see below for a discussion on how to transfer errors from ActiveRecord models.
67
67
 
68
68
  Any `StandardError` raised within a routine will be caught and transformed into a fatal error with `:kind` set to `:exception`. The caller of this routine can choose to reraise this exception by calling `reraise_exception!` on the returned errors object:
@@ -79,13 +79,13 @@ By default `raise_exception_if_any!` will raise a `StandardError` with a message
79
79
 
80
80
  A routine will automatically get both class- and instance-level `call`
81
81
  methods that take the same arguments as the `exec` method. The class-level
82
- call method simply instantiates a new instance of the routine and calls
83
- the instance-level call method (side note here is that this means that
82
+ call method simply instantiates a new instance of the routine and calls
83
+ the instance-level call method (side note here is that this means that
84
84
  routines aren't typically instantiated with state).
85
85
 
86
86
  When called, a routine returns a `Result` object, which is just a simple wrapper
87
- of the outputs and errors objects.
88
-
87
+ of the outputs and errors objects.
88
+
89
89
  result = MyRoutine.call(42)
90
90
  puts result.outputs[:bar] # => 84
91
91
 
@@ -93,71 +93,71 @@ of the outputs and errors objects.
93
93
  ### Nesting Routines
94
94
 
95
95
  As mentioned above, routines can call other routines. While this is of course possible just by calling the other routine's call method directly, it is strongly recommended that one routine call another routine using the provided `run` method. This method takes the name of the routine class and the arguments/block it expects in its call/exec methods. By using the `run` method, the called routine will be hooked into the common error and transaction mechanisms.
96
-
96
+
97
97
  When one routine is called within another using the `run` method, there is only one transaction used (barring any explicitly made in the code) and its isolation level is sufficiently strict for all routines involved.
98
-
98
+
99
99
  It is highly recommend, though not required, to call the `uses_routine` method to let the routine know which subroutines will be called within it. This will let a routine set its isolation level appropriately, and will enforce that only one transaction be used and that it be rolled back appropriately if any errors occur.
100
-
100
+
101
101
  Once a routine has been registered with the `uses_routine` call, it can be run by passing run the routine's Class or a symbol identifying the routine. This symbol can be set with the `:as` option. If not set, the symbol will be automatically set by converting the routine class' full name to a symbol. e.g:
102
-
102
+
103
103
  uses_routine CreateUser
104
104
  as: :cu
105
-
105
+
106
106
  and then you can call this routine with any of the following:
107
107
 
108
108
  * `run(:cu, ...)`
109
109
  * `run(:create_user, ...)`
110
110
  * `run(CreateUser, ...)`
111
111
  * `CreateUser.call(...)` (not recommended)
112
-
112
+
113
113
  #### Errors from Nested Routines
114
114
 
115
- `uses_routine` also provides a way to specify how errors relate to routine
116
- inputs. Take the following example. A `User` model calls `Routine1` which calls
115
+ `uses_routine` also provides a way to specify how errors relate to routine
116
+ inputs. Take the following example. A `User` model calls `Routine1` which calls
117
117
  `Routine2`.
118
-
118
+
119
119
  User --> Routine1.call(foo: "abcd4") --> Routine2.call(bar: "abcd4")
120
-
120
+
121
121
  An error occurs in `Routine2`, and Routine2 notes that the error is related
122
122
  to its `bar` input. If that error and its metadata bubble up to the `User`,
123
123
  the `User` won't have any idea what `bar` relates to -- the `User` only knows
124
124
  about the interface to `Routine1` and the `foo` parameter it gave it.
125
-
125
+
126
126
  `Routine1` knows that it will call `Routine2` and knows what its interface is. It can then specify how to map terminology from `Routine2` into `Routine1`'s context. E.g., in the following class:
127
-
127
+
128
128
  class Routine1
129
129
  lev_routine
130
130
  uses_routine Routine2,
131
- translations: {
131
+ translations: {
132
132
  inputs: { map: {bar: :foo} }
133
133
  }
134
134
  def exec(options)
135
135
  run(Routine2, bar: options[:foo])
136
136
  end
137
137
  end
138
-
138
+
139
139
  `Routine1` notes that any errors coming back from the call to `Routine2` related to `:bar` should be transfered into `Routine1`'s errors object as being related to `:foo`. In this way, the caller of `Routine1` will see errors related to the arguments he understands.
140
140
 
141
141
  In addition to the `map:` configuration for input transferral, there are three other configurations:
142
142
 
143
- 1. **Scoped** - Appends the provided scoping symbol (or symbol array) to the input symbol.
144
-
143
+ 1. **Scoped** - Appends the provided scoping symbol (or symbol array) to the input symbol.
144
+
145
145
  `{scope: SCOPING_SYMBOL_OR_SYMBOL_ARRAY}`
146
-
146
+
147
147
  e.g. with `{scope: :register}` and a call to a routine that has an input
148
- named `:first_name`, an error in that called routine related to its
149
- `:first_name` input will be translated so that the offending input is
148
+ named `:first_name`, an error in that called routine related to its
149
+ `:first_name` input will be translated so that the offending input is
150
150
  `[:register, :first_name]`.
151
-
151
+
152
152
  2. **Verbatim** - Uses the same term in the caller as the callee.
153
-
153
+
154
154
  `{type: :verbatim}`
155
-
155
+
156
156
  3. **Mapped** - Give an explicit, custom mapping:
157
-
157
+
158
158
  `{map: {called_input1: caller_input1, called_input2: :caller_input2}}`
159
-
160
- 4. **Scoped and mapped** - Give an explicit mapping, and also scope the
159
+
160
+ 4. **Scoped and mapped** - Give an explicit mapping, and also scope the
161
161
  translated terms. Just use `scope:` and `map:` from above in the same hash.
162
162
 
163
163
  If an input translation is unspecified, the default is scoped, with `SCOPING_SYMBOL_OR_ARRAY` equal to the `as:` option passed to `uses_routine`, if provided, or if that is not provided then the symbolized name of the routine class. E.g. for:
@@ -170,10 +170,10 @@ an errors generated on the `foo` input in `OtherRoutine` will be transferred up
170
170
 
171
171
  Via the `uses_routine` call, you can also ignore specified errors that occur
172
172
  in the called routine. e.g.:
173
-
173
+
174
174
  uses_routine DestroyUser,
175
175
  ignored_errors: [:cannot_destroy_non_temp_user]
176
-
176
+
177
177
  ignores errors with the provided code. The `ignore_errors` key must point
178
178
  to an array of code symbols or procs. If a proc is given, the proc will
179
179
  be called with the error that the routine is trying to add. If the proc
@@ -187,12 +187,12 @@ In addition to errors being transferred from subroutines to calling routines, a
187
187
  class Routine1
188
188
  lev_routine
189
189
  uses_routine Routine2,
190
- translations: {
190
+ translations: {
191
191
  outputs: { type: :verbatim }
192
192
  }
193
193
 
194
194
  def exec(options)
195
- run(Routine2, bar: options[:foo])
195
+ run(Routine2, bar: options[:foo])
196
196
  # Assuming Routine2 generates an output named "x", then outputs[:x] will be
197
197
  # available as of this line
198
198
  end
@@ -202,7 +202,7 @@ If the output translations are not specified, they will be scoped exactly like h
202
202
 
203
203
 
204
204
  Note if multiple outputs are transferred into the same named output (e.g. by calling the same routine over and over in a loop), an array of those outputs will be stored under that name.
205
-
205
+
206
206
  #### Overriding `uses_routine` Options
207
207
 
208
208
  Any option passed to uses_routine can also be passed directly to the run
@@ -234,20 +234,20 @@ When errors are captured inside an `ActiveRecord` errors object, you can use `tr
234
234
  ### Specifying Transaction Isolations
235
235
 
236
236
  A routine is automatically run within a transaction. The isolation level of the routine can be set by passing a `:transaction` option to the `lev_routine` call (or to the `lev_handler` call, if appropriate). The value must be one of the following:
237
-
237
+
238
238
  * `:no_transaction`
239
239
  * `:read_uncommitted`
240
240
  * `:read_committed`
241
241
  * `:repeatable_read`
242
242
  * `:serializable`
243
-
243
+
244
244
  Note that by setting an isolation level, you are stating the minimum isolation level at which a routine must be run. When routines are nested inside each other, the highest-specified isolation level from any one of them is used in the one transaction in which all of a routines' subroutines run.
245
245
 
246
246
  For example, if you write a routine that does a complex query, you might not need any transaction:
247
247
 
248
248
  class MyQueryRoutine
249
249
  lev_routine transaction: :no_transaction
250
-
250
+
251
251
  If unspecified, the default isolation is `:repeatable_read`.
252
252
 
253
253
  ### delegate_to_routine
@@ -266,12 +266,112 @@ When `delegate_to_routine` is called, the provided method will call the routine
266
266
 
267
267
  will alias the old `destroy` method as `destroy_original` and add a new `destroy` method that calls the `DestroyProduct` routine.
268
268
 
269
+ ### Express Calling of Routines
270
+
271
+ Routines commonly return one output. These routines are often named things like `GetUserEmail` or `IsFinalized`. Particularly
272
+ for boolean queries like `IsBlahBlah`, it is onerous to say:
273
+
274
+ ```ruby
275
+ if IsBlahBlah.call(arg1, arg2).outputs.some_output_containing_the_true_false_value
276
+ ```
277
+
278
+ As a convenience, routines can be called "expressly" (as in compactly) using the bracket operator. For example with the
279
+ following routine:
280
+
281
+ ```ruby
282
+ class AreArgumentsEqual
283
+ lev_routine
284
+
285
+ def exec(arg1, arg2)
286
+ outputs[:are_arguments_equal] = (arg1 == arg2)
287
+ end
288
+ end
289
+ ```
290
+
291
+ you could call it in the normal way:
292
+
293
+ ```ruby
294
+ if AreArgumentsEqual.call(201, 202).outputs.are_arguments_equal
295
+ # do something
296
+ end
297
+ ```
298
+
299
+ or you can call it using brackets:
300
+
301
+ ```ruby
302
+ if AreArgumentsEqual[201, 202]
303
+ # do something
304
+ end
305
+ ```
306
+
307
+ When using this bracket style of calling routines, Lev assumes that the value to be returned is named with the underscored
308
+ version of the routine name, e.g. `AreArgumentsEqual` has a default return value of `are_arguments_equal`. Module names
309
+ are disregarded when computing the default name.
310
+
311
+ The `express_output` can be overriden:
312
+
313
+ ```ruby
314
+ class AreArgumentsEqual
315
+ lev_routine, express_output: :answer
316
+
317
+ def exec(arg1, arg2)
318
+ outputs[:answer] = (arg1 == arg2)
319
+ end
320
+ end
321
+ ```
322
+
323
+ When calling with the bracket operator, any errors accumulated by the routine are raised in an exception (have to do this
324
+ since you have no other way to pay attention to the errors).
325
+
326
+ ### Delegates
327
+
328
+ If you have
329
+
330
+ ```ruby
331
+ class BarRoutine
332
+ lev_routine
333
+
334
+ def exec(alpha:, beta:)
335
+ # Do work
336
+ end
337
+ end
338
+ ```
339
+
340
+ you might have a reason to wrap this routine inside another, in which case you could write:
341
+
342
+ ```ruby
343
+ class FooRoutine
344
+ lev_routine
345
+
346
+ uses_routine BarRoutine,
347
+ translations: {
348
+ outputs: { type: :verbatim },
349
+ inputs: { type: :verbatim }
350
+ }
351
+
352
+ def exec(alpha:, beta:)
353
+ run(BarRoutine, alpha: alpha, beta: beta)
354
+ end
355
+ end
356
+ ```
357
+
358
+ or if you use the `delegates_to:` shortcut, you can instead equivalently wrap `BarRoutine` with:
359
+
360
+ ```ruby
361
+ class ShorterFooRoutine
362
+ lev_routine delegates_to: BarRoutine
363
+ end
364
+ ```
365
+
366
+ When using `delegates_to`, any `express_output` value set in the delegated routine is automatically
367
+ used again by the delegating routine.
368
+
269
369
  ### Other Routine Methods
270
-
370
+
271
371
  Routine class have access to a few other methods:
272
372
 
273
373
  1. a `runner` accessor which points to the routine which called it. If
274
- runner is nil that means that no other routine called it (some other
374
+ runner is nil that means that no other routine called it (some other
275
375
  code did)
276
376
  2. a `topmost_runner` accessor which points to the highest routine in the calling
277
377
  hierarchy (that routine whose 'runner' is nil)
@@ -289,7 +389,7 @@ Handlers...
289
389
  4. Map one-to-one with controller actions; by keeping the logic in each controller action encapsulated in a Handler, the code becomes independently-testable and also prevents the controller from being "fat" with 7 different actions all containing disparate logic touching different models.
290
390
 
291
391
  A class becomes a handler by calling `lev_handler` in its definition, e.g.:
292
-
392
+
293
393
  class MyHandler
294
394
  lev_handler
295
395
  ...
@@ -310,10 +410,10 @@ Additionally, the handler provides attributes to return the `errors` object and
310
410
 
311
411
  The `handle` method that you define should not return anything; they just set values in the errors and results objects. The documentation for each handler should explain what the results will be and any nonstandard data required to be passed in in the options.
312
412
 
313
- In addition to the class- and instance-level `call` methods provided by Lev::Routine, Handlers have a class-level `handle` method (an alias of the class-level `call` method). The convention for handlers is that the `call` methods (and this class-level `handle` method) take a hash of options/inputs. The instance-level `handle` method doesn't take any arguments since the arguments have been stored as instance variables by the time the instance-level handle method is called.
314
-
413
+ In addition to the class- and instance-level `call` methods provided by Lev::Routine, Handlers have a class-level `handle` method (an alias of the class-level `call` method). The convention for handlers is that the `call` methods (and this class-level `handle` method) take a hash of options/inputs. The instance-level `handle` method doesn't take any arguments since the arguments have been stored as instance variables by the time the instance-level handle method is called.
414
+
315
415
  Example:
316
-
416
+
317
417
  class MyHandler
318
418
  lev_handler
319
419
  protected
@@ -327,7 +427,7 @@ In addition to the class- and instance-level `call` methods provided by Lev::Rou
327
427
 
328
428
  ### paramify
329
429
 
330
- By declaring one or more `paramify` blocks in a handler, you can declare, group, cast, and validate parts of the `params` hash. Think of `paramify` as a way to declare an ad-hoc `ActiveModel` class to wrap incoming parameters. Normally, you only get easy validation of input parameters when those parameters are passed to an application model that is validated during a save. `paramify` lets you do this for any arbitrary collection of incoming parameters without requiring those parameters to live in application models.
430
+ By declaring one or more `paramify` blocks in a handler, you can declare, group, cast, and validate parts of the `params` hash. Think of `paramify` as a way to declare an ad-hoc `ActiveModel` class to wrap incoming parameters. Normally, you only get easy validation of input parameters when those parameters are passed to an application model that is validated during a save. `paramify` lets you do this for any arbitrary collection of incoming parameters without requiring those parameters to live in application models.
331
431
 
332
432
  The first argument to `paramify` is the key in params which points to a hash of params to be paramified. If this first argument is unspecified (or specified as `:paramify`, a reserved symbol), the entire params hash will be paramified. The block passed to paramify looks just like the guts of an ActiveAttr model.
333
433
 
@@ -338,13 +438,13 @@ For example, when the incoming params includes :search => {:type, :terms, :num_r
338
438
  validates :type, presence: true,
339
439
  inclusion: { in: %w(Name Username Any),
340
440
  message: "is not valid" }
341
-
441
+
342
442
  attribute :terms, type: String
343
443
  validates :terms, presence: true
344
-
444
+
345
445
  attribute :num_results, type: Integer
346
446
  validates :num_results, numericality: { only_integer: true,
347
- greater_than_or_equal_to: 0 }
447
+ greater_than_or_equal_to: 0 }
348
448
  end
349
449
 
350
450
  This will result in a `search_params` variable being available. `search_params.num_results` would be guaranteed to be an integer greater than or equal to zero. Note that if you want to use a "Boolean" type, you need to type it with a lowercase (`type: boolean`).
@@ -365,9 +465,9 @@ The following is a more complete example using the `paramify` block above:
365
465
 
366
466
  attribute :num_results, type: Integer
367
467
  validates :num_results, numericality: { only_integer: true,
368
- greater_than_or_equal_to: 0 }
468
+ greater_than_or_equal_to: 0 }
369
469
  end
370
-
470
+
371
471
  def handle
372
472
  # By this time, if there were any errors the handler would have
373
473
  # already populated the errors object and returned.
@@ -382,23 +482,23 @@ The following is a more complete example using the `paramify` block above:
382
482
  ### handle_with
383
483
 
384
484
  `handle_with` is a utility method for calling handlers from controllers. To use it, call `include Lev::HandleWith` in your relevant controllers (or in your ApplicationController):
385
-
485
+
386
486
  class ApplicationController
387
487
  include Lev::HandleWith
388
488
  ...
389
489
  end
390
-
490
+
391
491
  Then, call `handle_with` from your various controller actions, e.g.:
392
-
492
+
393
493
  handle_with(MyFormHandler,
394
494
  params: params,
395
495
  success: lambda { redirect_to 'show', notice: 'Success!'},
396
496
  failure: lambda { render 'new', alert: 'Error' })
397
-
497
+
398
498
  `handle_with` takes care of calling the handler and populates a `@handler_result` object with results and errors from running the handler.
399
-
499
+
400
500
  The 'success' and 'failure' lambdas are called if there aren't or are errors, respectively. Alternatively, if you supply a 'complete' lambda, that lambda will be called regardless of whether there are any errors. Inside these lambdas (and inside the views they connect to), the @handler_outcome variable containing the errors and results from the handler will be available.
401
-
501
+
402
502
  Specifying 'params' is optional. If you don't specify it, `handle_with` will use the entire params hash from the request.
403
503
 
404
504
  Handlers help us clean up controllers in our Rails projects. Instead of having a different piece of application logic in every controller action, a Lev-oriented app's controllers just end up being responsible for connecting routes to handlers, normally via a quick call to `handle_with`.
@@ -429,7 +529,7 @@ Consider the following example:
429
529
  <%= f.submit "Register", id: "register_submit" %>
430
530
  <% end %>
431
531
 
432
- Here, the form parameters will include
532
+ Here, the form parameters will include
433
533
 
434
534
  :register => {:username => 'bob79', :first_name => 'Bob', :password => 'password', :password_confirmation => 'password'}
435
535
 
@@ -507,17 +607,17 @@ When these guidelines are followed, model classes end up being very small and si
507
607
 
508
608
  ## Naming Conventions
509
609
 
510
- As mentioned above, a handler is intended to replace the logic in one controller action. As such, one convention that works well is to name a handler based on the controller name and the action name, e.g. for the `ProductsController#show` action, we would have a handler named `ProductsShow`.
610
+ As mentioned above, a handler is intended to replace the logic in one controller action. As such, one convention that works well is to name a handler based on the controller name and the action name, e.g. for the `ProductsController#show` action, we would have a handler named `ProductsShow`.
511
611
 
512
612
  Routines on the other hand are more or less glorified functions that work with multiple models to get something done, so we typically start their names with verbs, e.g. `CreateUser`, `SetPassword`, `ConfirmEmail`, etc.
513
613
 
514
614
  ## Differences between Lev and Rails' Concerns
515
615
 
516
- Both Lev and Concerns remove lines of code from models, but the major difference between the two is that with Concerns, the code still lives logically in the models whereas code in Lev is completely outside of and separate from the models.
616
+ Both Lev and Concerns remove lines of code from models, but the major difference between the two is that with Concerns, the code still lives logically in the models whereas code in Lev is completely outside of and separate from the models.
517
617
 
518
- Lev's routines (and handlers) know about models, but the models don't know anything about nor are they dependent on the code in routines*. This makes the models simpler and more stable (a Good Thing).
618
+ Lev's routines (and handlers) know about models, but the models don't know anything about nor are they dependent on the code in routines*. This makes the models simpler and more stable (a Good Thing).
519
619
 
520
- Since a Concern's code is essentially embedded in model code, if that Concern breaks it can potentially break other unrelated features, something that can't happen with routines.
620
+ Since a Concern's code is essentially embedded in model code, if that Concern breaks it can potentially break other unrelated features, something that can't happen with routines.
521
621
 
522
622
  Routines are especially good when some use case needs to query or change multiple models. With a routine all of the logic for that use case is in one file. With a concern, that code could be in multiple models and multiple concerns.
523
623
 
data/lib/lev.rb CHANGED
@@ -27,12 +27,12 @@ require "lev/transaction_isolation"
27
27
 
28
28
  module Lev
29
29
  class << self
30
-
30
+
31
31
  ###########################################################################
32
32
  #
33
33
  # Configuration machinery.
34
34
  #
35
- # To configure Lev, put the following code in your applications
35
+ # To configure Lev, put the following code in your applications
36
36
  # initialization logic (eg. in the config/initializers in a Rails app)
37
37
  #
38
38
  # Lev.configure do |config|
@@ -40,7 +40,7 @@ module Lev
40
40
  # ...
41
41
  # end
42
42
  #
43
-
43
+
44
44
  def configure
45
45
  yield configuration
46
46
  end
@@ -53,13 +53,15 @@ module Lev
53
53
  # This HTML class is added to form fields that caused errors
54
54
  attr_accessor :form_error_class
55
55
  attr_accessor :security_transgression_error
56
-
57
- def initialize
56
+ attr_accessor :illegal_argument_error
57
+
58
+ def initialize
58
59
  @form_error_class = 'error'
59
60
  @security_transgression_error = Lev::SecurityTransgression
61
+ @illegal_argument_error = Lev::IllegalArgument
60
62
  super
61
63
  end
62
64
  end
63
-
65
+
64
66
  end
65
67
  end
@@ -1,10 +1,10 @@
1
1
  module Lev
2
2
 
3
- # A collection of Error objects.
3
+ # A collection of Error objects.
4
4
  #
5
5
  class Errors < Array
6
6
 
7
- def add(fail, args={})
7
+ def add(fail, args={})
8
8
  args[:kind] ||= :lev
9
9
  error = Error.new(args)
10
10
  return if ignored_error_procs.any?{|proc| proc.call(error)}
@@ -16,8 +16,8 @@ module Lev
16
16
  proc = arg.is_a?(Symbol) ?
17
17
  Proc.new{|error| error.code == arg} :
18
18
  arg
19
-
20
- raise IllegalArgument if !proc.respond_to?(:call)
19
+
20
+ raise Lev.configuration.illegal_argument_error if !proc.respond_to?(:call)
21
21
 
22
22
  ignored_error_procs.push(proc)
23
23
  end
@@ -31,6 +31,10 @@ module Lev
31
31
  self.any? {|error| [error.offending_inputs].flatten.include? input}
32
32
  end
33
33
 
34
+ def raise_exception_if_any!(exception_type = StandardError)
35
+ raise exception_type, collect{|error| error.message}.join('; ') if any?
36
+ end
37
+
34
38
  protected
35
39
 
36
40
  def ignored_error_procs
@@ -38,4 +42,4 @@ module Lev
38
42
  end
39
43
 
40
44
  end
41
- end
45
+ end
@@ -1,4 +1,5 @@
1
1
  class Lev::IsolationMismatch < StandardError; end
2
2
  class Lev::SecurityTransgression < StandardError; end
3
3
  class Lev::AlgorithmError < StandardError; end
4
- class Lev::AbstractMethodCalled < StandardError; end
4
+ class Lev::AbstractMethodCalled < StandardError; end
5
+ class Lev::IllegalArgument < StandardError; end
@@ -7,6 +7,20 @@ class Object
7
7
  # Routine configuration
8
8
  options[:transaction] ||= Lev::TransactionIsolation.mysql_default.symbol
9
9
  @transaction_isolation = Lev::TransactionIsolation.new(options[:transaction])
10
+
11
+ @delegates_to = options[:delegates_to]
12
+ if @delegates_to
13
+ uses_routine @delegates_to,
14
+ translations: {
15
+ outputs: { type: :verbatim },
16
+ inputs: { type: :verbatim }
17
+ }
18
+
19
+ @express_output ||= @delegates_to.express_output
20
+ end
21
+
22
+ # Set this after dealing with "delegates_to" in case it set a value
23
+ @express_output ||= options[:express_output] || self.name.demodulize.underscore
10
24
  end
11
25
  end
12
26
 
@@ -14,7 +28,7 @@ class Object
14
28
  class_eval do
15
29
  include Lev::Handler
16
30
  end
17
-
31
+
18
32
  # Do routine configuration
19
33
  options[:skip_routine_include] = true
20
34
  lev_routine(options)
@@ -22,4 +36,4 @@ class Object
22
36
  # Do handler configuration (none currently)
23
37
  end
24
38
 
25
- end
39
+ end
@@ -1,15 +1,15 @@
1
1
  module Lev
2
-
2
+
3
3
  # A "routine" in the Lev world is a piece of code that is responsible for
4
4
  # doing one thing, normally acting on one or more other objects. Routines
5
- # are particularly useful when the thing that needs to be done involves
5
+ # are particularly useful when the thing that needs to be done involves
6
6
  # making changes to multiple other objects. In an OO/MVC world, an operation
7
7
  # that involves multiple objects might be implemented by spreading that logic
8
8
  # among those objects. However, that leads to classes having more
9
9
  # responsibilities than they should (and more knowlege of other classes than
10
10
  # they should) as well as making the code hard to follow.
11
11
  #
12
- # Routines typically don't have any persistent state that is used over and
12
+ # Routines typically don't have any persistent state that is used over and
13
13
  # over again; they are created, used, and forgotten. A routine is a glorified
14
14
  # function with a special single-responsibility purpose.
15
15
  #
@@ -22,19 +22,19 @@ module Lev
22
22
  #
23
23
  # in its definition.
24
24
  #
25
- # Other than that, all a routine has to do is implement an "exec" method
25
+ # Other than that, all a routine has to do is implement an "exec" method
26
26
  # that takes arbitrary arguments and that adds errors to an internal
27
27
  # array-like "errors" object and outputs to a "outputs" hash.
28
28
  #
29
29
  # A routine returns an "Result" object, which is just a simple wrapper
30
- # of the outputs and errors objects.
30
+ # of the outputs and errors objects.
31
31
  #
32
32
  # A routine will automatically get both class- and instance-level "call"
33
33
  # methods that take the same arguments as the "exec" method. The class-level
34
- # call method simply instantiates a new instance of the routine and calls
35
- # the instance-level call method (side note here is that this means that
34
+ # call method simply instantiates a new instance of the routine and calls
35
+ # the instance-level call method (side note here is that this means that
36
36
  # routines aren't typically instantiated with state).
37
- #
37
+ #
38
38
  # A routine is automatically run within a transaction. The isolation level
39
39
  # of the routine can be set by passing a :transaction option to the lev_routine
40
40
  # call (or to the lev_handler call, if appropriate). The value must be one of
@@ -53,9 +53,9 @@ module Lev
53
53
  # As mentioned above, routines can call other routines. While this is of
54
54
  # course possible just by calling the other routine's call method directly,
55
55
  # it is strongly recommended that one routine call another routine using the
56
- # provided "run" method. This method takes the name of the routine class
56
+ # provided "run" method. This method takes the name of the routine class
57
57
  # and the arguments/block it expects in its call/exec methods. By using the
58
- # run method, the called routine will be hooked into the common error and
58
+ # run method, the called routine will be hooked into the common error and
59
59
  # transaction mechanisms.
60
60
  #
61
61
  # When one routine is called within another using the run method, there is
@@ -65,11 +65,11 @@ module Lev
65
65
  # It is highly recommend, though not required, to call the "uses_routine"
66
66
  # method to let the routine know which subroutines will be called within it.
67
67
  # This will let a routine set its isolation level appropriately, and will
68
- # enforce that only one transaction be used and that it be rolled back
68
+ # enforce that only one transaction be used and that it be rolled back
69
69
  # appropriately if any errors occur.
70
70
  #
71
71
  # Once a routine has been registered with the "uses_routine" call, it can
72
- # be run by passing run the routine's Class or a symbol identifying the
72
+ # be run by passing run the routine's Class or a symbol identifying the
73
73
  # routine. This symbol can be set with the :as option. If not set, the
74
74
  # symbol will be automatically set by converting the routine class' full
75
75
  # name to a symbol. e.g:
@@ -85,8 +85,8 @@ module Lev
85
85
  #
86
86
  # run(:create_user, ...)
87
87
  #
88
- # uses_routine also provides a way to specify how errors relate to routine
89
- # inputs. Take the following example. A user calls Routine1 which calls
88
+ # uses_routine also provides a way to specify how errors relate to routine
89
+ # inputs. Take the following example. A user calls Routine1 which calls
90
90
  # Routine2.
91
91
  #
92
92
  # User --> Routine1.call(foo: "abcd4") --> Routine2.call(bar: "abcd4")
@@ -96,14 +96,14 @@ module Lev
96
96
  # the User won't have any idea what "bar" relates to -- the User only knows
97
97
  # about the interface to Routine1 and the "foo" parameter it gave it.
98
98
  #
99
- # Routine1 knows that it will call Routine2 and knows what its interface is.
100
- # It can then specify how to map terminology from Routine2 into Routine1's
99
+ # Routine1 knows that it will call Routine2 and knows what its interface is.
100
+ # It can then specify how to map terminology from Routine2 into Routine1's
101
101
  # context. E.g., in the following class:
102
102
  #
103
103
  # class Routine1
104
104
  # lev_routine
105
105
  # uses_routine Routine2,
106
- # translations: {
106
+ # translations: {
107
107
  # inputs: { map: {bar: :foo} }
108
108
  # }
109
109
  # def exec(options)
@@ -111,26 +111,26 @@ module Lev
111
111
  # end
112
112
  # end
113
113
  #
114
- # Routine1 notes that any errors coming back from the call to Routine2
114
+ # Routine1 notes that any errors coming back from the call to Routine2
115
115
  # related to :bar should be transfered into Routine1's errors object
116
116
  # as being related to :foo. In this way, the caller of Routine1 will see
117
117
  # errors related to the arguments he understands.
118
118
  #
119
119
  # Translations can also be supplied for "outputs" in addition to "inputs".
120
- # Output translations control how a called routine's Result outputs are
120
+ # Output translations control how a called routine's Result outputs are
121
121
  # transfered to the calling routine's outputs. Note if multiple outputs are
122
- # transferred into the same named output, an array of those outputs will be
123
- # store. The contents of the "inputs" and "outputs" hashes can be of the
122
+ # transferred into the same named output, an array of those outputs will be
123
+ # store. The contents of the "inputs" and "outputs" hashes can be of the
124
124
  # following form:
125
125
  #
126
126
  # 1) Scoped. Appends the provided scoping symbol (or symbol array) to
127
- # the input symbol.
127
+ # the input symbol.
128
128
  #
129
129
  # {scope: SCOPING_SYMBOL_OR_SYMBOL_ARRAY}
130
130
  #
131
131
  # e.g. with {scope: :register} and a call to a routine that has an input
132
- # named :first_name, an error in that called routine related to its
133
- # :first_name input will be translated so that the offending input is
132
+ # named :first_name, an error in that called routine related to its
133
+ # :first_name input will be translated so that the offending input is
134
134
  # [:register, :first_name].
135
135
  #
136
136
  # 2) Verbatim. Uses the same term in the caller as the callee.
@@ -141,7 +141,7 @@ module Lev
141
141
  #
142
142
  # {map: {called_input1: caller_input1, called_input2: :caller_input2}}
143
143
  #
144
- # 4) Scoped and mapped. Give an explicit mapping, and also scope the
144
+ # 4) Scoped and mapped. Give an explicit mapping, and also scope the
145
145
  # translated terms. Just use scope: and map: from above in the same hash.
146
146
  #
147
147
  # Via the uses_routine call, you can also ignore specified errors that occur
@@ -170,12 +170,12 @@ module Lev
170
170
  # Routine class have access to a few other methods:
171
171
  #
172
172
  # 1) a "runner" accessor which points to the routine which called it. If
173
- # runner is nil that means that no other routine called it (some other
173
+ # runner is nil that means that no other routine called it (some other
174
174
  # code did)
175
- #
175
+ #
176
176
  # 2) a "topmost_runner" which points to the highest routine in the calling
177
177
  # hierarchy (that routine whose 'runner' is nil)
178
- #
178
+ #
179
179
  # References:
180
180
  # http://ducktypo.blogspot.com/2010/08/why-inheritance-sucks.html
181
181
  #
@@ -200,13 +200,19 @@ module Lev
200
200
  new.call(*args, &block)
201
201
  end
202
202
 
203
+ def [](*args, &block)
204
+ result = call(*args, &block)
205
+ result.errors.raise_exception_if_any!
206
+ result.outputs.send(@express_output)
207
+ end
208
+
203
209
  # Called at a routine's class level to foretell which other routines will
204
210
  # be used when this routine executes. Helpful for figuring out ahead of
205
211
  # time what kind of transaction isolation level should be used.
206
212
  def uses_routine(routine_class, options={})
207
213
  symbol = options[:as] || class_to_symbol(routine_class)
208
214
 
209
- raise IllegalArgument, "Routine #{routine_class} has already been registered" \
215
+ raise Lev.configuration.illegal_argument_error, "Routine #{routine_class} has already been registered" \
210
216
  if nested_routines[symbol]
211
217
 
212
218
  nested_routines[symbol] = {
@@ -221,6 +227,14 @@ module Lev
221
227
  @transaction_isolation ||= TransactionIsolation.mysql_default
222
228
  end
223
229
 
230
+ def express_output
231
+ @express_output
232
+ end
233
+
234
+ def delegates_to
235
+ @delegates_to
236
+ end
237
+
224
238
  def nested_routines
225
239
  @nested_routines ||= {}
226
240
  end
@@ -236,9 +250,13 @@ module Lev
236
250
  @after_transaction_blocks = []
237
251
 
238
252
  in_transaction do
239
- catch :fatal_errors_encountered do
253
+ catch :fatal_errors_encountered do
240
254
  begin
241
- exec(*args, &block)
255
+ if self.class.delegates_to
256
+ run(self.class.delegates_to, *args, &block)
257
+ else
258
+ exec(*args, &block)
259
+ end
242
260
  end
243
261
  end
244
262
  end
@@ -261,7 +279,7 @@ module Lev
261
279
 
262
280
  if other_routine.is_a? Array
263
281
  if other_routine.size != 2
264
- raise IllegalArgument, "when first arg to run is an array, it must have two arguments"
282
+ raise Lev.configuration.illegal_argument_error, "when first arg to run is an array, it must have two arguments"
265
283
  end
266
284
 
267
285
  other_routine = other_routine[0]
@@ -273,16 +291,16 @@ module Lev
273
291
  other_routine
274
292
  when Class
275
293
  self.class.class_to_symbol(other_routine)
276
- else
294
+ else
277
295
  self.class.class_to_symbol(other_routine.class)
278
296
  end
279
297
 
280
298
  nested_routine = self.class.nested_routines[symbol] || {}
281
299
 
282
300
  if nested_routine.empty? && other_routine == symbol
283
- raise IllegalArgument,
301
+ raise Lev.configuration.illegal_argument_error,
284
302
  "Routine symbol #{other_routine} does not point to a registered routine"
285
- end
303
+ end
286
304
 
287
305
  #
288
306
  # Get an instance of the routine and make sure it is a routine
@@ -291,8 +309,9 @@ module Lev
291
309
  other_routine = nested_routine[:routine_class] || other_routine
292
310
  other_routine = other_routine.new if other_routine.is_a? Class
293
311
 
294
- raise IllegalArgument, "Can only run another nested routine" \
295
- if !(other_routine.includes_module? Lev::Routine)
312
+ if !(other_routine.includes_module? Lev::Routine)
313
+ raise Lev.configuration.illegal_argument_error, "Can only run another nested routine"
314
+ end
296
315
 
297
316
  #
298
317
  # Merge passed-in options with those set in uses_routine, the former taking
@@ -308,10 +327,10 @@ module Lev
308
327
 
309
328
  options[:translations] ||= {}
310
329
 
311
- input_mapper = new_term_mapper(options[:translations][:inputs]) ||
330
+ input_mapper = new_term_mapper(options[:translations][:inputs]) ||
312
331
  new_term_mapper({ scope: symbol })
313
332
 
314
- output_mapper = new_term_mapper(options[:translations][:outputs]) ||
333
+ output_mapper = new_term_mapper(options[:translations][:outputs]) ||
315
334
  new_term_mapper({ scope: symbol })
316
335
 
317
336
  #
@@ -357,7 +376,7 @@ module Lev
357
376
  errors.add(false, args)
358
377
  end
359
378
 
360
- # Utility method to transfer errors from a source to this routine. The
379
+ # Utility method to transfer errors from a source to this routine. The
361
380
  # provided input_mapper maps the language of the errors in the source to
362
381
  # the language of this routine. If fail_if_errors is true, this routine
363
382
  # will throw an error condition that causes execution of this routine to stop
@@ -399,33 +418,33 @@ module Lev
399
418
  @runner = runner
400
419
 
401
420
  if topmost_runner.class.transaction_isolation.weaker_than(self.class.transaction_isolation)
402
- raise IsolationMismatch,
403
- "The routine being run has a stronger isolation requirement than " +
421
+ raise IsolationMismatch,
422
+ "The routine being run has a stronger isolation requirement than " +
404
423
  "the isolation being used by the routine(s) running it; call the " +
405
424
  "'uses' method in the running routine's initializer"
406
425
  end
407
426
  end
408
427
 
409
- def in_transaction(options={})
428
+ def in_transaction(options={})
410
429
  if transaction_run_by?(self)
411
430
  isolation_symbol = self.class.transaction_isolation.symbol
412
431
  if ActiveRecord::VERSION::MAJOR >= 4
413
432
  begin
414
- ActiveRecord::Base.transaction(isolation: isolation_symbol) do
433
+ ActiveRecord::Base.transaction(isolation: isolation_symbol) do
415
434
  yield
416
435
  raise ActiveRecord::Rollback if errors?
417
436
  end
418
437
  rescue ActiveRecord::TransactionIsolationError
419
438
  # Silently ignore isolation errors
420
- ActiveRecord::Base.transaction do
439
+ ActiveRecord::Base.transaction do
421
440
  yield
422
441
  raise ActiveRecord::Rollback if errors?
423
442
  end
424
443
  end
425
444
  else
426
445
  ActiveRecord::Base.isolation_level(isolation_symbol) do
427
- ActiveRecord::Base.transaction do
428
- yield
446
+ ActiveRecord::Base.transaction do
447
+ yield
429
448
  raise ActiveRecord::Rollback if errors?
430
449
  end
431
450
  end
@@ -443,7 +462,7 @@ module Lev
443
462
  when :verbatim
444
463
  return TermMapper.verbatim
445
464
  else
446
- raise IllegalArgument, "unknown :type value: #{options[:type]}"
465
+ raise Lev.configuration.illegal_argument_error, "unknown :type value: #{options[:type]}"
447
466
  end
448
467
  end
449
468
 
@@ -455,4 +474,4 @@ module Lev
455
474
  end
456
475
 
457
476
  end
458
- end
477
+ end
@@ -2,7 +2,7 @@ module Lev
2
2
  class TransactionIsolation
3
3
 
4
4
  def initialize(symbol)
5
- raise IllegalArgument, "Invalid isolation symbol" if !@@symbols_to_isolation_levels.has_key?(symbol)
5
+ raise Lev.configuration.illegal_argument_error, "Invalid isolation symbol" if !@@symbols_to_isolation_levels.has_key?(symbol)
6
6
  @symbol = symbol
7
7
  end
8
8
 
@@ -36,7 +36,7 @@ module Lev
36
36
  def eql?(other)
37
37
  self == other
38
38
  end
39
-
39
+
40
40
  attr_reader :symbol
41
41
 
42
42
  protected
@@ -56,4 +56,4 @@ module Lev
56
56
  attr_writer :symbol
57
57
 
58
58
  end
59
- end
59
+ end
@@ -11,4 +11,16 @@ module Lev
11
11
  end
12
12
 
13
13
  end
14
- end
14
+ end
15
+
16
+ module Kernel
17
+ def eigenclass
18
+ class << self
19
+ self
20
+ end
21
+ end
22
+
23
+ def includes_module?(mod)
24
+ eigenclass.included_modules.include?(mod)
25
+ end
26
+ end
@@ -1,3 +1,3 @@
1
1
  module Lev
2
- VERSION = "4.0.0"
2
+ VERSION = "4.1.0"
3
3
  end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe DelegatingRoutine do
4
+
5
+ it "should delegate" do
6
+ result = DelegatingRoutine.call(1,8)
7
+ expect(result.outputs[:answer]).to eq 9
8
+ end
9
+
10
+ it "should delegate with assumed express_output" do
11
+ result = DelegatingRoutine[1,8]
12
+ expect(result).to eq 9
13
+ end
14
+
15
+ end
@@ -0,0 +1,10 @@
1
+ class DelegatedRoutine
2
+ lev_routine express_output: :answer
3
+
4
+ protected
5
+
6
+ def exec(alpha, beta)
7
+ outputs[:answer] = alpha + beta
8
+ end
9
+
10
+ end
@@ -0,0 +1,5 @@
1
+ require_relative './delegated_routine'
2
+
3
+ class DelegatingRoutine
4
+ lev_routine delegates_to: DelegatedRoutine
5
+ end
metadata CHANGED
@@ -1,20 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lev
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0
5
- prerelease:
4
+ version: 4.1.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - JP Slavinsky
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2015-03-03 00:00:00.000000000 Z
11
+ date: 2015-04-16 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: activemodel
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
17
  - - ! '>='
20
18
  - !ruby/object:Gem::Version
@@ -22,7 +20,6 @@ dependencies:
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
24
  - - ! '>='
28
25
  - !ruby/object:Gem::Version
@@ -30,7 +27,6 @@ dependencies:
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: activerecord
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
31
  - - ! '>='
36
32
  - !ruby/object:Gem::Version
@@ -38,7 +34,6 @@ dependencies:
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
38
  - - ! '>='
44
39
  - !ruby/object:Gem::Version
@@ -46,7 +41,6 @@ dependencies:
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: actionpack
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
45
  - - ! '>='
52
46
  - !ruby/object:Gem::Version
@@ -54,7 +48,6 @@ dependencies:
54
48
  type: :runtime
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
52
  - - ! '>='
60
53
  - !ruby/object:Gem::Version
@@ -62,7 +55,6 @@ dependencies:
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: transaction_isolation
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
59
  - - ! '>='
68
60
  - !ruby/object:Gem::Version
@@ -70,7 +62,6 @@ dependencies:
70
62
  type: :runtime
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
66
  - - ! '>='
76
67
  - !ruby/object:Gem::Version
@@ -78,7 +69,6 @@ dependencies:
78
69
  - !ruby/object:Gem::Dependency
79
70
  name: transaction_retry
80
71
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
72
  requirements:
83
73
  - - ! '>='
84
74
  - !ruby/object:Gem::Version
@@ -86,7 +76,6 @@ dependencies:
86
76
  type: :runtime
87
77
  prerelease: false
88
78
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
79
  requirements:
91
80
  - - ! '>='
92
81
  - !ruby/object:Gem::Version
@@ -94,7 +83,6 @@ dependencies:
94
83
  - !ruby/object:Gem::Dependency
95
84
  name: active_attr
96
85
  requirement: !ruby/object:Gem::Requirement
97
- none: false
98
86
  requirements:
99
87
  - - ! '>='
100
88
  - !ruby/object:Gem::Version
@@ -102,7 +90,6 @@ dependencies:
102
90
  type: :runtime
103
91
  prerelease: false
104
92
  version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
93
  requirements:
107
94
  - - ! '>='
108
95
  - !ruby/object:Gem::Version
@@ -110,7 +97,6 @@ dependencies:
110
97
  - !ruby/object:Gem::Dependency
111
98
  name: hashie
112
99
  requirement: !ruby/object:Gem::Requirement
113
- none: false
114
100
  requirements:
115
101
  - - ! '>='
116
102
  - !ruby/object:Gem::Version
@@ -118,7 +104,6 @@ dependencies:
118
104
  type: :runtime
119
105
  prerelease: false
120
106
  version_requirements: !ruby/object:Gem::Requirement
121
- none: false
122
107
  requirements:
123
108
  - - ! '>='
124
109
  - !ruby/object:Gem::Version
@@ -126,7 +111,6 @@ dependencies:
126
111
  - !ruby/object:Gem::Dependency
127
112
  name: bundler
128
113
  requirement: !ruby/object:Gem::Requirement
129
- none: false
130
114
  requirements:
131
115
  - - ! '>='
132
116
  - !ruby/object:Gem::Version
@@ -134,7 +118,6 @@ dependencies:
134
118
  type: :development
135
119
  prerelease: false
136
120
  version_requirements: !ruby/object:Gem::Requirement
137
- none: false
138
121
  requirements:
139
122
  - - ! '>='
140
123
  - !ruby/object:Gem::Version
@@ -142,7 +125,6 @@ dependencies:
142
125
  - !ruby/object:Gem::Dependency
143
126
  name: rake
144
127
  requirement: !ruby/object:Gem::Requirement
145
- none: false
146
128
  requirements:
147
129
  - - ! '>='
148
130
  - !ruby/object:Gem::Version
@@ -150,7 +132,6 @@ dependencies:
150
132
  type: :development
151
133
  prerelease: false
152
134
  version_requirements: !ruby/object:Gem::Requirement
153
- none: false
154
135
  requirements:
155
136
  - - ! '>='
156
137
  - !ruby/object:Gem::Version
@@ -158,7 +139,6 @@ dependencies:
158
139
  - !ruby/object:Gem::Dependency
159
140
  name: rspec
160
141
  requirement: !ruby/object:Gem::Requirement
161
- none: false
162
142
  requirements:
163
143
  - - ! '>='
164
144
  - !ruby/object:Gem::Version
@@ -166,7 +146,6 @@ dependencies:
166
146
  type: :development
167
147
  prerelease: false
168
148
  version_requirements: !ruby/object:Gem::Requirement
169
- none: false
170
149
  requirements:
171
150
  - - ! '>='
172
151
  - !ruby/object:Gem::Version
@@ -174,7 +153,6 @@ dependencies:
174
153
  - !ruby/object:Gem::Dependency
175
154
  name: sqlite3
176
155
  requirement: !ruby/object:Gem::Requirement
177
- none: false
178
156
  requirements:
179
157
  - - ! '>='
180
158
  - !ruby/object:Gem::Version
@@ -182,7 +160,6 @@ dependencies:
182
160
  type: :development
183
161
  prerelease: false
184
162
  version_requirements: !ruby/object:Gem::Requirement
185
- none: false
186
163
  requirements:
187
164
  - - ! '>='
188
165
  - !ruby/object:Gem::Version
@@ -190,7 +167,6 @@ dependencies:
190
167
  - !ruby/object:Gem::Dependency
191
168
  name: debugger
192
169
  requirement: !ruby/object:Gem::Requirement
193
- none: false
194
170
  requirements:
195
171
  - - ! '>='
196
172
  - !ruby/object:Gem::Version
@@ -198,7 +174,6 @@ dependencies:
198
174
  type: :development
199
175
  prerelease: false
200
176
  version_requirements: !ruby/object:Gem::Requirement
201
- none: false
202
177
  requirements:
203
178
  - - ! '>='
204
179
  - !ruby/object:Gem::Version
@@ -206,7 +181,6 @@ dependencies:
206
181
  - !ruby/object:Gem::Dependency
207
182
  name: rails
208
183
  requirement: !ruby/object:Gem::Requirement
209
- none: false
210
184
  requirements:
211
185
  - - ! '>='
212
186
  - !ruby/object:Gem::Version
@@ -214,7 +188,6 @@ dependencies:
214
188
  type: :development
215
189
  prerelease: false
216
190
  version_requirements: !ruby/object:Gem::Requirement
217
- none: false
218
191
  requirements:
219
192
  - - ! '>='
220
193
  - !ruby/object:Gem::Version
@@ -226,6 +199,10 @@ executables: []
226
199
  extensions: []
227
200
  extra_rdoc_files: []
228
201
  files:
202
+ - LICENSE.txt
203
+ - README.md
204
+ - Rakefile
205
+ - lib/lev.rb
229
206
  - lib/lev/better_active_model_errors.rb
230
207
  - lib/lev/delegate_to_routine.rb
231
208
  - lib/lev/error.rb
@@ -244,12 +221,9 @@ files:
244
221
  - lib/lev/transaction_isolation.rb
245
222
  - lib/lev/utilities.rb
246
223
  - lib/lev/version.rb
247
- - lib/lev.rb
248
- - LICENSE.txt
249
- - Rakefile
250
- - README.md
251
224
  - spec/create_sprocket_spec.rb
252
225
  - spec/deep_merge_spec.rb
226
+ - spec/delegates_to_spec.rb
253
227
  - spec/errors_spec.rb
254
228
  - spec/outputs_spec.rb
255
229
  - spec/paramify_handler_spec.rb
@@ -258,6 +232,8 @@ files:
258
232
  - spec/sprocket_handler_spec.rb
259
233
  - spec/sprocket_spec.rb
260
234
  - spec/support/create_sprocket.rb
235
+ - spec/support/delegated_routine.rb
236
+ - spec/support/delegating_routine.rb
261
237
  - spec/support/paramify_handler_a.rb
262
238
  - spec/support/paramify_handler_b.rb
263
239
  - spec/support/sprocket.rb
@@ -265,37 +241,31 @@ files:
265
241
  homepage: http://github.com/lml/lev
266
242
  licenses:
267
243
  - MIT
244
+ metadata: {}
268
245
  post_install_message:
269
246
  rdoc_options: []
270
247
  require_paths:
271
248
  - lib
272
249
  required_ruby_version: !ruby/object:Gem::Requirement
273
- none: false
274
250
  requirements:
275
251
  - - ! '>='
276
252
  - !ruby/object:Gem::Version
277
253
  version: '0'
278
- segments:
279
- - 0
280
- hash: 2525822979360039563
281
254
  required_rubygems_version: !ruby/object:Gem::Requirement
282
- none: false
283
255
  requirements:
284
256
  - - ! '>='
285
257
  - !ruby/object:Gem::Version
286
258
  version: '0'
287
- segments:
288
- - 0
289
- hash: 2525822979360039563
290
259
  requirements: []
291
260
  rubyforge_project:
292
- rubygems_version: 1.8.23.2
261
+ rubygems_version: 2.4.6
293
262
  signing_key:
294
- specification_version: 3
263
+ specification_version: 4
295
264
  summary: Ride the rails but don't touch them.
296
265
  test_files:
297
266
  - spec/create_sprocket_spec.rb
298
267
  - spec/deep_merge_spec.rb
268
+ - spec/delegates_to_spec.rb
299
269
  - spec/errors_spec.rb
300
270
  - spec/outputs_spec.rb
301
271
  - spec/paramify_handler_spec.rb
@@ -304,6 +274,8 @@ test_files:
304
274
  - spec/sprocket_handler_spec.rb
305
275
  - spec/sprocket_spec.rb
306
276
  - spec/support/create_sprocket.rb
277
+ - spec/support/delegated_routine.rb
278
+ - spec/support/delegating_routine.rb
307
279
  - spec/support/paramify_handler_a.rb
308
280
  - spec/support/paramify_handler_b.rb
309
281
  - spec/support/sprocket.rb