verifly 0.2.0.0 → 0.2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://travis-ci.org/umbrellio/verifly.svg?branch=master)](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: []
|