verifly 0.2.0.0 → 0.2.0.1
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 +193 -0
- data/lib/verifly/version.rb +1 -1
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7171d204c82a0f84dd0b8780dda21a0c527687e1
|
4
|
+
data.tar.gz: cec080bcb1b9e2e38a3dd3434f8f18c498293f64
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3f8f1bcaf78681238fd4935cc831e4b5716aa937fe92caafffb4aa1762837d0091da69a891d4b33ce25126a40d3193cacb930a23e7c9ec1adf33dbfb2b73b850
|
7
|
+
data.tar.gz: 2ede721d805ba64742b50743b16952609e6c82529d0a634f82bf32b7152660becd766c687147e9ae369aa8e02211cb12b80a4da7284d950abdd147ad8f6a2fea
|
data/README.md
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
# Verifly v0.2
|
2
|
+
[](https://travis-ci.org/umbrellio/verifly)
|
3
|
+
|
4
|
+
This gem provides an api to run sequential checks like
|
5
|
+
'ActiveModel::Validations' do, but with generic messages instead of errors.
|
6
|
+
|
7
|
+
It also provides additional components to build it which could be used
|
8
|
+
to imporve code readability. See [Applicator](#Applicator),
|
9
|
+
[ApplicatorWithOptions](#ApplicatorWithOptions) and
|
10
|
+
[ClassBuilder](#ClassBuilder) along with [Verifier](#Verifier)
|
11
|
+
|
12
|
+
## Instalation
|
13
|
+
|
14
|
+
```
|
15
|
+
$ gem install verifly
|
16
|
+
```
|
17
|
+
|
18
|
+
and then in code
|
19
|
+
|
20
|
+
```
|
21
|
+
require 'verifly'
|
22
|
+
```
|
23
|
+
|
24
|
+
## ClassBuilder
|
25
|
+
|
26
|
+
example:
|
27
|
+
|
28
|
+
```lang=ruby
|
29
|
+
Abstract = Struct.new(:data)
|
30
|
+
extend Verifly::ClassBuilder::Mixin
|
31
|
+
|
32
|
+
class WithString < self
|
33
|
+
def self.build_class(x)
|
34
|
+
self if x.is_a?(String)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
Generic = Class.new(self)
|
39
|
+
|
40
|
+
self.buildable_classes = [WithString, Generic]
|
41
|
+
# or, vice versa
|
42
|
+
def self.buildable_classes
|
43
|
+
[WithString, Generic]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
Abstract.build("foo") # => WithString.new("foo")
|
48
|
+
Abstract.build(:foo) # => Generic.new("foo")
|
49
|
+
```
|
50
|
+
|
51
|
+
or see it at rubydoc.info
|
52
|
+
|
53
|
+
Why don't just use Uber::Builder?
|
54
|
+
([Uber](https://github.com/apotonick/uber) is cool, you should try it)
|
55
|
+
There are two reasons: firstly, it is an unnecessary dependency.
|
56
|
+
We dont want npm hell, do we? Uber::Builder realy does not do much work,
|
57
|
+
it's just a pattern. Secondly, this implementation looks more clear to me,
|
58
|
+
because children are deciding whether they will handle arguments, not parents.
|
59
|
+
|
60
|
+
So to use it, you have to:
|
61
|
+
|
62
|
+
1. Write some classes with duck type `.class_builder(*args)`
|
63
|
+
|
64
|
+
2. Invoke `Verifly::ClassBuilder.new([<%= array_of_classes %>]).call(*args)`
|
65
|
+
|
66
|
+
3. ????
|
67
|
+
|
68
|
+
4. PROFIT
|
69
|
+
|
70
|
+
It's simple and clear, but not very sugary. So, otherwise, you may do
|
71
|
+
following:
|
72
|
+
|
73
|
+
1. Write an abstract class
|
74
|
+
|
75
|
+
2. Extend `Verifly::ClassBuilder::Mixin`
|
76
|
+
|
77
|
+
3. Inherit from the abstract class in different implementations
|
78
|
+
|
79
|
+
4. If some implementations have common ancestors
|
80
|
+
(not including the abstract class), you can implement common ancestor's
|
81
|
+
`.build_class` in terms of super (i.e.
|
82
|
+
`def self.build_class(x); super if x.is_a?(String); end`)
|
83
|
+
|
84
|
+
5. Change `.build_class` of other classes like `self if ...`.
|
85
|
+
Don't change default implementation's `.build_class`
|
86
|
+
|
87
|
+
6. Setup `.buildable_classes` on the abstract class, mentioning only direct
|
88
|
+
children if you done step 4
|
89
|
+
|
90
|
+
7. Optionally redefine `.build` in abstract class, if you want
|
91
|
+
to separate `build_class` and constructor params
|
92
|
+
|
93
|
+
8. Use `.build` instead of `new`
|
94
|
+
|
95
|
+
## Applicator
|
96
|
+
|
97
|
+
Applicator is designed to wrap applications of
|
98
|
+
[applicable](https://en.wikipedia.org/wiki/Sepulka) objects
|
99
|
+
around some binding in some context
|
100
|
+
|
101
|
+
example:
|
102
|
+
|
103
|
+
```lang=ruby
|
104
|
+
object = OpenStruct.new(foo: :bar)
|
105
|
+
Applicator.call(:foo, object, {}) # => :bar
|
106
|
+
Applicator.call('foo', object, {}) # => :bar
|
107
|
+
Applicator.call('context', object, {}) # => {}
|
108
|
+
Applicator.call(-> { foo }, object, {}) # => :bar
|
109
|
+
Applicator.call(->(context) { context[foo] }, object, bar: :baz) # => :baz
|
110
|
+
Applicator.call(true, object, {}) # => true
|
111
|
+
|
112
|
+
foo = :bar
|
113
|
+
Applicator.call(:foo, binding, {}) # => :bar
|
114
|
+
Applicator.call('object.foo', binding, {}) # => :bar
|
115
|
+
```
|
116
|
+
|
117
|
+
Applicator is good, but in most cases
|
118
|
+
[ApplicatorWithOptions](#ApplicatorWithOptions) would be a better option.
|
119
|
+
|
120
|
+
## ApplicatorWithOptions
|
121
|
+
|
122
|
+
ApplicatorWithOptions is an applicator with options.
|
123
|
+
The options are `if: ` and `unless: `. Same as in ActiveModel::Validations,
|
124
|
+
they are applied to the same binding. Main action is executed
|
125
|
+
only if `if: ` evaluates to truthy and `unless: ` evaluates to falsey.
|
126
|
+
|
127
|
+
See examples:
|
128
|
+
|
129
|
+
```lang=ruby
|
130
|
+
ApplicatorWithOptions.new(:foo, if: -> { true }).call(binding, {}) # => foo
|
131
|
+
|
132
|
+
ApplicatorWithOptions.new(:foo, if: -> (context) { context[:bar] })
|
133
|
+
.call(binding, { bar: true }) # => foo
|
134
|
+
|
135
|
+
ApplicatorWithOptions.new(:foo, if: { bar: true }).call(binding, :bar) # => foo
|
136
|
+
|
137
|
+
ApplicatorWithOptions.new(:foo, unless: -> { true })
|
138
|
+
.call(binding, {}) # => nil
|
139
|
+
ApplicatorWithOptions.new(:foo, unless: -> (context) { context[:bar] })
|
140
|
+
.call(binding, { bar: true }) # => foo
|
141
|
+
ApplicatorWithOptions.new(:foo, unless: { bar: true })
|
142
|
+
.call(binding, :bar) # => nil
|
143
|
+
```
|
144
|
+
|
145
|
+
## Verifier
|
146
|
+
|
147
|
+
The last, but the most interesting component is Verifier.
|
148
|
+
Verifiers use ApplciatorWithOptions to execute generic procedures.
|
149
|
+
Procedures should call `message!` if they want to yield something.
|
150
|
+
Note that you should implement `message!` by yourself (in terms of super)
|
151
|
+
|
152
|
+
```lang=ruby
|
153
|
+
class MyVerifier < Verifly::Verifier
|
154
|
+
Message = Struct.new(:text)
|
155
|
+
verify :foo, if: { foo: true }
|
156
|
+
|
157
|
+
private
|
158
|
+
|
159
|
+
def message!(text)
|
160
|
+
super { Message.new(text) }
|
161
|
+
end
|
162
|
+
|
163
|
+
def foo
|
164
|
+
message!('Something is wrong') if Fixnum != Bignum
|
165
|
+
end
|
166
|
+
end
|
167
|
+
```
|
168
|
+
|
169
|
+
In addition to Applicator's power, you also can nest your verifiers
|
170
|
+
to split the logic
|
171
|
+
|
172
|
+
```lang=ruby
|
173
|
+
class MyVerifier < Verifly::Verifier
|
174
|
+
Message = Struct.new(:text)
|
175
|
+
verify_with ChildVerifier, if: -> (context) { cotnext[:foo] }
|
176
|
+
|
177
|
+
private
|
178
|
+
|
179
|
+
def message!(text)
|
180
|
+
super { Message.new(text) }
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
class ChildVerifier < MyVerifier
|
185
|
+
verify %q(message!("it's alive!"))
|
186
|
+
end
|
187
|
+
```
|
188
|
+
|
189
|
+
## Yard documentation
|
190
|
+
|
191
|
+
This gem uses yard to generate documentation about its API.
|
192
|
+
Visit http://www.rubydoc.info/github/umbrellio/verifly/master to see
|
193
|
+
actual documentation for master.
|
data/lib/verifly/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: verifly
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.0.
|
4
|
+
version: 0.2.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexander Smirnov
|
@@ -150,13 +150,15 @@ dependencies:
|
|
150
150
|
- - "~>"
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '1.1'
|
153
|
-
description: '
|
153
|
+
description: 'An api to run sequential checks like ''ActiveModel::Validations'' do,
|
154
|
+
but with generic messages instead of errors. See more info at [http://www.rubydoc.info/gems/verifly/0.2.0.1] '
|
154
155
|
email:
|
155
156
|
- begdory4@gmail.com
|
156
157
|
executables: []
|
157
158
|
extensions: []
|
158
159
|
extra_rdoc_files: []
|
159
160
|
files:
|
161
|
+
- README.md
|
160
162
|
- lib/verifly.rb
|
161
163
|
- lib/verifly/applicator.rb
|
162
164
|
- lib/verifly/applicator_with_options.rb
|
@@ -166,7 +168,8 @@ files:
|
|
166
168
|
homepage: https://github.com/umbrellio/verifly
|
167
169
|
licenses:
|
168
170
|
- MIT
|
169
|
-
metadata:
|
171
|
+
metadata:
|
172
|
+
yard.run: yri
|
170
173
|
post_install_message:
|
171
174
|
rdoc_options: []
|
172
175
|
require_paths:
|
@@ -186,6 +189,5 @@ rubyforge_project:
|
|
186
189
|
rubygems_version: 2.5.2
|
187
190
|
signing_key:
|
188
191
|
specification_version: 4
|
189
|
-
summary:
|
190
|
-
generic messages instead of errors
|
192
|
+
summary: See more info at [http://www.rubydoc.info/gems/verifly/0.2.0.1]
|
191
193
|
test_files: []
|