subroutine 0.1.4 → 0.2.0
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/README.md +18 -1
- data/lib/subroutine/op.rb +16 -28
- data/lib/subroutine/type_caster.rb +8 -3
- data/lib/subroutine/version.rb +2 -2
- data/test/subroutine/base_test.rb +24 -0
- data/test/subroutine/type_caster_test.rb +4 -4
- data/test/support/ops.rb +1 -0
- metadata +17 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 212d37192891dfad2e6fced663590d50f37302ee
|
4
|
+
data.tar.gz: 2ded356bfcfe49f9b697aba9784325fe2ce4426a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b4dc8ba20210de9eb5d2260f5cc98f95fe6a9c74e9a0ee625434a683a1773273efdc5461e2356238ca63bd7457c9554748f35fecad40a2153b665b81953ac5d1
|
7
|
+
data.tar.gz: cf30411572f31668031cc96ac76cb0ce4edb6132b22f9990a38023d32e312b53468179a31dea8604e25e54e0ac69189a7df13f338559c000d8980bb4aada2a2e
|
data/README.md
CHANGED
@@ -154,9 +154,26 @@ class MyOp < ::Subroutine::Op
|
|
154
154
|
end
|
155
155
|
```
|
156
156
|
|
157
|
+
Since ops can use other ops, sometimes it's nice to explicitly state the inputs are valid. To "inherit" all the inputs from another op, simply use `inputs_from`.
|
158
|
+
|
159
|
+
```ruby
|
160
|
+
class MyOp < ::Subroutine::Op
|
161
|
+
string :token
|
162
|
+
inputs_from MyOtherOp
|
163
|
+
|
164
|
+
protected
|
165
|
+
|
166
|
+
def perform
|
167
|
+
verify_token!
|
168
|
+
MyOtherOp.submit! params.except(:token)
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
172
|
+
```
|
173
|
+
|
157
174
|
#### Validations
|
158
175
|
|
159
|
-
Since Ops
|
176
|
+
Since Ops include ActiveModel::Model, validations can be used just like any other ActiveModel object.
|
160
177
|
|
161
178
|
```ruby
|
162
179
|
class MyOp < ::Subroutine::Op
|
data/lib/subroutine/op.rb
CHANGED
@@ -96,15 +96,12 @@ module Subroutine
|
|
96
96
|
|
97
97
|
def #{field_name}=(v)
|
98
98
|
config = #{field_name}_config
|
99
|
-
|
99
|
+
v = type_caster.cast(v, config[:type])
|
100
|
+
@params["#{field_name}"] = v
|
100
101
|
end
|
101
102
|
|
102
103
|
def #{field_name}
|
103
|
-
|
104
|
-
config = #{field_name}_config
|
105
|
-
deflt = config[:default]
|
106
|
-
deflt = deflt.call if deflt.respond_to?(:call)
|
107
|
-
type_caster.cast(deflt, config[:type])
|
104
|
+
@params["#{field_name}"]
|
108
105
|
end
|
109
106
|
|
110
107
|
def #{field_name}_config
|
@@ -137,7 +134,7 @@ module Subroutine
|
|
137
134
|
|
138
135
|
def initialize(inputs = {})
|
139
136
|
@original_params = inputs.with_indifferent_access
|
140
|
-
@params
|
137
|
+
@params = sanitize_params(@original_params)
|
141
138
|
end
|
142
139
|
|
143
140
|
def errors
|
@@ -154,10 +151,6 @@ module Subroutine
|
|
154
151
|
# the action which should be invoked upon form submission (from the controller)
|
155
152
|
def submit
|
156
153
|
observe_submission do
|
157
|
-
@params = filter_params(@original_params)
|
158
|
-
|
159
|
-
set_accessors(@params)
|
160
|
-
|
161
154
|
validate_and_perform
|
162
155
|
end
|
163
156
|
|
@@ -173,15 +166,6 @@ module Subroutine
|
|
173
166
|
|
174
167
|
protected
|
175
168
|
|
176
|
-
# ensure that our type caster has the opportunity to cast each key
|
177
|
-
def params
|
178
|
-
out = {}
|
179
|
-
@params.keys.each do |k|
|
180
|
-
out[k] = send(k)
|
181
|
-
end
|
182
|
-
out
|
183
|
-
end
|
184
|
-
|
185
169
|
def type_caster
|
186
170
|
@type_caster ||= ::Subroutine::TypeCaster.new
|
187
171
|
end
|
@@ -247,15 +231,19 @@ module Subroutine
|
|
247
231
|
|
248
232
|
# if you want to use strong parameters or something in your form object you can do so here.
|
249
233
|
# by default we just slice the inputs to the defined fields
|
250
|
-
def
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
234
|
+
def sanitize_params(inputs)
|
235
|
+
out = {}.with_indifferent_access
|
236
|
+
self._fields.each_pair do |field, config|
|
237
|
+
if inputs.has_key?(field)
|
238
|
+
out[field] = type_caster.cast(inputs[field], config[:type])
|
239
|
+
elsif config[:default]
|
240
|
+
deflt = config[:default]
|
241
|
+
deflt = deflt.call if deflt.respond_to?(:call)
|
242
|
+
out[field] = type_caster.cast(deflt, config[:type])
|
243
|
+
end
|
258
244
|
end
|
245
|
+
|
246
|
+
out
|
259
247
|
end
|
260
248
|
|
261
249
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'date'
|
2
2
|
require 'time'
|
3
|
+
require 'bigdecimal'
|
3
4
|
require 'active_support/core_ext/object/blank'
|
4
5
|
require 'active_support/core_ext/object/try'
|
5
6
|
require 'active_support/core_ext/array/wrap'
|
@@ -10,7 +11,8 @@ module Subroutine
|
|
10
11
|
|
11
12
|
TYPES = {
|
12
13
|
:integer => [:int, :integer, :epoch],
|
13
|
-
:number => [:number, :float
|
14
|
+
:number => [:number, :float],
|
15
|
+
:decimal => [:decimal, :big_decimal],
|
14
16
|
:string => [:string, :text],
|
15
17
|
:boolean => [:bool, :boolean],
|
16
18
|
:iso_date => [:iso_date],
|
@@ -29,7 +31,10 @@ module Subroutine
|
|
29
31
|
when *TYPES[:integer]
|
30
32
|
cast_number(value).try(:to_i)
|
31
33
|
when *TYPES[:number]
|
32
|
-
cast_number(value)
|
34
|
+
cast_number(value).try(:to_f)
|
35
|
+
when *TYPES[:decimal]
|
36
|
+
d = cast_number(value)
|
37
|
+
d ? BigDecimal(d.to_s) : nil
|
33
38
|
when *TYPES[:string]
|
34
39
|
cast_string(value)
|
35
40
|
when *TYPES[:boolean]
|
@@ -57,7 +62,7 @@ module Subroutine
|
|
57
62
|
def cast_number(value)
|
58
63
|
val = cast_string(value).strip
|
59
64
|
return nil if val.blank?
|
60
|
-
val
|
65
|
+
val
|
61
66
|
end
|
62
67
|
|
63
68
|
def cast_string(value)
|
data/lib/subroutine/version.rb
CHANGED
@@ -144,5 +144,29 @@ module Subroutine
|
|
144
144
|
assert_equal [], op.errors[:whatever]
|
145
145
|
end
|
146
146
|
|
147
|
+
def test_it_sets_the_params_immediately_and_includes_defaults
|
148
|
+
op = ::AdminSignupOp.new(email: "foo")
|
149
|
+
assert_equal({
|
150
|
+
"priveleges" => "min",
|
151
|
+
"email" => "foo"
|
152
|
+
}, op.params)
|
153
|
+
end
|
154
|
+
|
155
|
+
def test_it_overrides_defaults_with_nils
|
156
|
+
op = ::AdminSignupOp.new(email: "foo", priveleges: nil)
|
157
|
+
assert_equal({
|
158
|
+
"priveleges" => nil,
|
159
|
+
"email" => "foo"
|
160
|
+
}, op.params)
|
161
|
+
end
|
162
|
+
|
163
|
+
def test_it_casts_params_on_the_way_in
|
164
|
+
op = ::TypeCastOp.new(integer_input: "25")
|
165
|
+
assert_equal(25, op.params["integer_input"])
|
166
|
+
|
167
|
+
op.decimal_input = "25.3"
|
168
|
+
assert_equal(BigDecimal("25.3"), op.params["decimal_input"])
|
169
|
+
end
|
170
|
+
|
147
171
|
end
|
148
172
|
end
|
@@ -115,8 +115,8 @@ module Subroutine
|
|
115
115
|
op.object_input = {foo: 'bar'}
|
116
116
|
assert_equal({'foo' => 'bar'}, op.object_input)
|
117
117
|
|
118
|
-
op.object_input = {"foo" => {
|
119
|
-
assert_equal({"foo" => {
|
118
|
+
op.object_input = {"foo" => {"bar" => :baz}}
|
119
|
+
assert_equal({"foo" => {"bar" => :baz}}, op.object_input)
|
120
120
|
end
|
121
121
|
|
122
122
|
def test_array_inputs
|
@@ -132,8 +132,8 @@ module Subroutine
|
|
132
132
|
op.array_input = ['foo']
|
133
133
|
assert_equal ['foo'], op.array_input
|
134
134
|
|
135
|
-
op.array_input = {
|
136
|
-
assert_equal [{
|
135
|
+
op.array_input = {"bar" => true}
|
136
|
+
assert_equal [{"bar" => true}], op.array_input
|
137
137
|
end
|
138
138
|
|
139
139
|
def test_date_inputs
|
data/test/support/ops.rb
CHANGED
metadata
CHANGED
@@ -1,83 +1,83 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: subroutine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Nelson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-08-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - '>='
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 4.0.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 4.0.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ~>
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '1.7'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ~>
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '1.7'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ~>
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '10.0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ~>
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '10.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: minitest
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - '>='
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: minitest-reporters
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - '>='
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - '>='
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
description: An interface for creating feature-driven operations.
|
@@ -87,8 +87,8 @@ executables: []
|
|
87
87
|
extensions: []
|
88
88
|
extra_rdoc_files: []
|
89
89
|
files:
|
90
|
-
-
|
91
|
-
-
|
90
|
+
- .gitignore
|
91
|
+
- .travis.yml
|
92
92
|
- Gemfile
|
93
93
|
- LICENSE.txt
|
94
94
|
- README.md
|
@@ -120,17 +120,17 @@ require_paths:
|
|
120
120
|
- lib
|
121
121
|
required_ruby_version: !ruby/object:Gem::Requirement
|
122
122
|
requirements:
|
123
|
-
- -
|
123
|
+
- - '>='
|
124
124
|
- !ruby/object:Gem::Version
|
125
125
|
version: '0'
|
126
126
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
127
127
|
requirements:
|
128
|
-
- -
|
128
|
+
- - '>='
|
129
129
|
- !ruby/object:Gem::Version
|
130
130
|
version: '0'
|
131
131
|
requirements: []
|
132
132
|
rubyforge_project:
|
133
|
-
rubygems_version: 2.
|
133
|
+
rubygems_version: 2.0.14.1
|
134
134
|
signing_key:
|
135
135
|
specification_version: 4
|
136
136
|
summary: Feature-driven operation objects.
|