verifly 0.1.0.0 → 0.2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4f523cb22087d0d7c74367fd62024dcdfb54304e
4
- data.tar.gz: 3d6c1a22923b9e3c2878cbed2dd6df65295a0405
3
+ metadata.gz: bb480769ef6ceb801e8d09f52eb9eab8a31bd356
4
+ data.tar.gz: fb911427e5d26cb1f10ae5142af217aae51110fc
5
5
  SHA512:
6
- metadata.gz: eb92359f062778ff644ccd41576b4023fcfcfe0af935b0c6edcf549ec4f9e5ea439bb24f617a0003935431313762925620f2e10366bffcad860d48873862ebf7
7
- data.tar.gz: 033ac456b04c5cfec227311a83ba3f16f32790632ee9966e103c8ea2d2d09fb36ce83642ec7ccefd9316e32ce65166188014cd613c7997b230d900b924be1ab6
6
+ metadata.gz: e22e09f78908ed3e451c3ce90d1e1c7d439cb1c69c8c356c4fd858ea2bbd3a071713c62666d6c74e364bc57faa61207cd3425e897b76fc834a1394f2bbe8bcb5
7
+ data.tar.gz: c5f4a1fd4a51b470cc12c5b4f57086a0e526919abbbbb949ef6781d3efb2e2b6645b879a14a4866ebeecb9ffaf4bb504ab2607e6f4258d0f61aa642ef1016c39
data/lib/verifly.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Verifly provides several usefull classes, but most important
4
- # is Verifier. Other provided classes are it's dependency.
5
- # See README.md or their own documentation for more info about usage
3
+ # Verifly provides several useful classes, but Verifier is the most
4
+ # important one, while others depend on it.
5
+ # See README.md or in-code documentation for more info.
6
6
  module Verifly
7
7
  autoload :VERSION, 'verifly/version'
8
8
 
@@ -33,7 +33,7 @@ module Verifly
33
33
  end
34
34
 
35
35
  # MethodExtractor is used when applicable is a symbol.
36
- # It extracts extracts method from binding_ and executes it on binding_
36
+ # It extracts a method from binding_ and executes it on binding_
37
37
  # (so it works just like send except it sends nothing
38
38
  # when method arity is zero).
39
39
  # @example
@@ -42,14 +42,14 @@ module Verifly
42
42
  # # or => User.new.foo, if it does not accept context
43
43
  class MethodExtractor < self
44
44
  # @param applicable [Symbol]
45
- # @return MethodExtractor if applicable is Symbol
45
+ # @return MethodExtractor if applicable is a Symbol
46
46
  # @return [nil] otherwise
47
47
  def self.build_class(applicable)
48
48
  self if applicable.is_a?(Symbol)
49
49
  end
50
50
 
51
- # @param binding_ [#instance_exec] target to apply applicable
52
- # @param context additional info to send it to applicable
51
+ # @param binding_ [#instance_exec] target to apply applicable to
52
+ # @param context additional info to send to applicable
53
53
  # @return application result
54
54
  def call(binding_, context)
55
55
  if binding_.is_a?(Binding)
@@ -61,9 +61,9 @@ module Verifly
61
61
 
62
62
  private
63
63
 
64
- # When Binding is target, we have to respect both methods and variables
65
- # @param binding_ [Binding] target to apply applicable
66
- # @param context additional info to send it to applicable
64
+ # When Binding is a target, we have to respect both methods and variables
65
+ # @param binding_ [Binding] target to apply applicable to
66
+ # @param context additional info to send to applicable
67
67
  # @return application result
68
68
  def call_on_binding(binding_, context)
69
69
  if binding_.receiver.respond_to?(applicable)
@@ -74,21 +74,21 @@ module Verifly
74
74
  end
75
75
  end
76
76
 
77
- # InstanceEvaluator is used for string. It works like instance_eval or
77
+ # InstanceEvaluator is used for strings. It works like instance_eval or
78
78
  # Binding#eval depending on binding_ class
79
79
  # @example
80
80
  # Applicator.call('foo if context[:foo]', binding_, context)
81
81
  # # => foo if context[:foo]
82
82
  class InstanceEvaluator < self
83
83
  # @param applicable [String]
84
- # @return InstanceEvaluator if applicable is String
84
+ # @return InstanceEvaluator if applicable is a String
85
85
  # @return [nil] otherwise
86
86
  def self.build_class(applicable)
87
87
  self if applicable.is_a?(String)
88
88
  end
89
89
 
90
- # @param binding_ [#instance_exec] target to apply applicable
91
- # @param context additional info to send it to applicable
90
+ # @param binding_ [#instance_exec] target to apply applicable to
91
+ # @param context additional info to send to applicable
92
92
  # @return application result
93
93
  def call(binding_, context)
94
94
  if binding_.is_a?(Binding)
@@ -111,10 +111,10 @@ module Verifly
111
111
  end
112
112
 
113
113
  # ProcApplicatior is used when #to_proc is available.
114
- # It works not just with procs, but also with hashes etc
115
- # @example with proc
114
+ # It works not only with procs, but also with hashes etc
115
+ # @example with a proc
116
116
  # Applicator.call(-> { foo }, binding_, context) # => foo
117
- # @example with hash
117
+ # @example with a hash
118
118
  # Applicator.call(Hash[foo: true], binding_, :foo) # => true
119
119
  # Applicator.call(Hash[foo: true], binding_, :bar) # => nil
120
120
  class ProcApplicatior < self
@@ -125,8 +125,8 @@ module Verifly
125
125
  self if applicable.respond_to?(:to_proc)
126
126
  end
127
127
 
128
- # @param binding_ [#instance_exec] target to apply applicable
129
- # @param context additional info to send it to applicable
128
+ # @param binding_ [#instance_exec] target to apply applicable to
129
+ # @param context additional info to send to applicable
130
130
  # @return application result
131
131
  def call(binding_, context)
132
132
  invoke_lambda(applicable.to_proc, binding_, context)
@@ -151,9 +151,9 @@ module Verifly
151
151
  attr_accessor :applicable
152
152
 
153
153
  # Applies applicable on binding_ with context
154
- # @todo add @see #initialize when it's todo done
154
+ # @todo add @see #initialize when its todo is done
155
155
  # @param applicable [applicable]
156
- # see examples in defenitions of sublcasses
156
+ # see examples in definitions of subclasses
157
157
  # @param binding_ [#instance_exec]
158
158
  # where should applicable be applied. It could be either a generic object,
159
159
  # where it would be `instance_exec`uted, or a binding_
@@ -168,7 +168,7 @@ module Verifly
168
168
  # Always use build instead of new
169
169
  # @todo add more examples right here
170
170
  # @param applicable [applicable]
171
- # see examples in sublcasses defenitions
171
+ # see examples in definitions of sublclasses
172
172
  # @api private
173
173
  def initialize(applicable)
174
174
  self.applicable = applicable
@@ -189,7 +189,7 @@ module Verifly
189
189
 
190
190
  private
191
191
 
192
- # invokes lambda respecting it's arity
192
+ # invokes lambda respecting its arity
193
193
  # @param [Proc] lambda
194
194
  # @param binding_ [#instance_exec] binding_ would be used in application
195
195
  # @param context param would be passed if lambda arity > 0
@@ -9,25 +9,32 @@ module Verifly
9
9
  # @attr action [Applicator]
10
10
  # main action to apply on call
11
11
  # @attr if_condition [Applicator]
12
- # main action only apply if this applies to truthy value
12
+ # main action only apply if condition evaluates to truthy value
13
13
  # @attr unless_condition [Applicator]
14
- # main action only apply if this applies to falsey value
14
+ # main action only apply if condition evaluates to falsey value
15
15
  class ApplicatorWithOptions
16
16
  attr_accessor :action, :if_condition, :unless_condition
17
17
 
18
+ # @!method initialize(action = block, options = {}, &block)
18
19
  # @param action [applicable] main action
19
20
  # @option options [applicable] :if
20
- # main action only apply if this applies to truthy value
21
+ # main action is only applied if this evaluates to truthy value
21
22
  # @option options [applicable] :unless
22
- # main action only apply if this applies to falsey value
23
- def initialize(action, **options)
23
+ # main action is only applied if this evaluates to falsey value
24
+ # @raise [ArgumentError] if there is more than two arguments and block
25
+ # @raise [ArgumentError] if there is zero arguments and no block
26
+ def initialize(*args, &block)
27
+ action, options, *rest = block ? [block, *args] : args
28
+ options ||= {}
29
+ raise ArgumentError unless action && rest.empty?
30
+
24
31
  self.action = Applicator.build(action)
25
32
  self.if_condition = Applicator.build(options.fetch(:if, true))
26
33
  self.unless_condition = Applicator.build(options.fetch(:unless, false))
27
34
  end
28
35
 
29
- # Applies main action if if_condition applyd to truthy value
30
- # and unless_condition applyd to falsey value
36
+ # Applies main action if if_condition is evaluated to truthy value
37
+ # and unless_condition is evaluated to falsey value
31
38
  # @param binding_ [#instance_exec]
32
39
  # binding to apply (see Applicator)
33
40
  # @param context
@@ -1,27 +1,28 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Verifly
4
- # ClassBuilder is something like Uber::Builder, but it
5
- # allows the child classes to decide whether they will be used.
6
- # I find it much more OOPish
4
+ # ClassBuilder is similar to Uber::Builder, but it
5
+ # allows child classes to decide whether they will be used.
6
+ # I find it much more object-oriented
7
7
  # @attr klasses [Array(Class)]
8
8
  # classes to iterate during search of most suitable
9
9
  class ClassBuilder
10
- # Mixin provides useful methods to integrate builder subsystem.
10
+ # Mixin provides useful methods to integrate into builder subsystem.
11
11
  # Feel free to override or just never include it.
12
12
  # @attr_writer [Array(Class)] buildable_classes
13
13
  # Array of classes which will be checked if they
14
14
  # suite constructor arguments. Order matters
15
15
  module Mixin
16
- # Array of classes which would be checked if they
16
+ # Array of classes which will be checked if they
17
17
  # suite constructor arguments. Order matters
18
18
  # @param klasses [Array(Class)]
19
19
  def buildable_classes=(klasses)
20
20
  @class_builder = ClassBuilder.new(klasses).freeze
21
21
  end
22
22
 
23
- # Default implementation of build_class. Feel free to change
24
- # You also have to override it in buildable_classes
23
+ # Default implementation of build_class.
24
+ # Feel free to change it, but you'll have to override it in
25
+ # buildable_classes
25
26
  def build_class(*args, &block)
26
27
  if @class_builder
27
28
  @class_builder.call(*args, &block)
@@ -15,35 +15,54 @@ module Verifly
15
15
 
16
16
  attr_accessor :model, :messages
17
17
 
18
- # @example with block
18
+ # @!method self.verify(action = block, options = {}, &block)
19
+ # @example with a block
19
20
  # verify { |context| message!() if context[:foo] }
20
- # @example with proc
21
+ # @example with a proc
21
22
  # verify -> (context) { message!() if context[:foo] }
22
- # @example with hash
23
+ # @example with a hash
23
24
  # verify -> { message!() } if: { foo: true }
24
- # @example cotnext could be ommited from lambda params
25
+ # @example context can be provided as a lambda param
25
26
  # verify -> { message!() }, if: -> (context) { context[:foo] }
26
- # @example with symbol
27
+ # @example with a symbol
27
28
  # verify :foo, if: :bar
28
29
  # # calls #foo if #bar is true
29
- # # bar could either accept context or not
30
- # @example with string
30
+ # # bar can accept context if desired
31
+ # @example with a string
31
32
  # verify 'message!() if context[:foo]'
32
33
  # verify 'message!()', if: 'context[:foo]'
33
- # @example with descedant
34
- # verify DescendantClass
35
- # # calls DescendantClass.call(model, context) and merges it's messages
36
- # @param verifier [#to_proc|Symbol|String|Class|nil]
34
+ # @param action [#to_proc|Symbol|String|nil]
37
35
  # verifier defenition, see examples
38
36
  # @option options [#to_proc|Symbol|String|nil] if (true)
37
+ # call verifier only if block invocation result is truthy
38
+ # @option options [#to_proc|Symbol|String|nil] unless (false)
39
+ # call verifier only if block invocation result is falsey
40
+ # @yield [context] yields on `#verfify!` calls
41
+ # @raise [ArgumentError] if there is more than two arguments and block
42
+ # @raise [ArgumentError] if there is zero arguments and no block
43
+ # @return [Array] list of all defined verifiers
44
+ def self.verify(*args, &block)
45
+ bound_applicators << ApplicatorWithOptions.new(*args, &block)
46
+ end
47
+
48
+ # Calls DescendantClass.call(model, context) and merges its messages.
49
+ # DescendantClass should be a descendant of current class
50
+ # @param name [String, Class]
51
+ # name of descendant class or descendant class itself
52
+ # @option options [#to_proc|Symbol|String|nil] if (true)
39
53
  # call verifier if only block invocation result is truthy
40
54
  # @option options [#to_proc|Symbol|String|nil] unless (false)
41
55
  # call verifier if only block invocation result is falsey
42
- # @yield context on `#verfify!` calls
43
56
  # @return [Array] list of all verifiers already defined
44
- def self.verify(*args, &block)
45
- bound_applicators <<
46
- ApplicatorWithOptionsBuilder.call(self, *args, &block)
57
+ def self.verify_with(name, options = {})
58
+ verify(options) do |context|
59
+ verifier = name.is_a?(String) ? Object.const_get(name, false) : name
60
+ raise ArgumentError, <<~ERROR unless verifier < self.class
61
+ Nested verifiers should be inherited from verifier they nested are in
62
+ ERROR
63
+
64
+ messages.concat(verifier.call(model, context))
65
+ end
47
66
  end
48
67
 
49
68
  # @return [Array(ApplicatorWithOptions)]
@@ -53,8 +72,8 @@ module Verifly
53
72
  end
54
73
 
55
74
  # @param model generic model to validate
56
- # @param context context in which it would be valdiated
57
- # @return [Array] list of messages yielded by verifier
75
+ # @param context context in which it is valdiated
76
+ # @return [Array] list of messages yielded by the verifier
58
77
  def self.call(model, context = {})
59
78
  new(model).verify!(context)
60
79
  end
@@ -65,8 +84,8 @@ module Verifly
65
84
  self.messages = []
66
85
  end
67
86
 
68
- # @param context context in which model would be valdiated
69
- # @return [Array] list of messages yielded by verifier
87
+ # @param context context in which model is valdiated
88
+ # @return [Array] list of messages yielded by the verifier
70
89
  def verify!(context = {})
71
90
  self.messages = []
72
91
 
@@ -80,7 +99,8 @@ module Verifly
80
99
  private
81
100
 
82
101
  # @abstract
83
- # implement it like `super { Message.new(status, text, description) }`
102
+ # implementation example:
103
+ # `super { Message.new(status, text, description) }`
84
104
  # @return new message (yield result)
85
105
  def message!(*)
86
106
  new_message = yield
@@ -3,10 +3,10 @@
3
3
  module Verifly
4
4
  # Specifies Verifly version
5
5
  #
6
- # Semantical naming: 0.a.b.c where
7
- # * 0 is for unreleased
8
- # * a is for public api changes
9
- # * b is for private api changes
10
- # * c is for changes, not changing private api
11
- VERSION = '0.1.0.0'
6
+ # Semantic versioning: 0.a.b.c where
7
+ # * 0 stands for unreleased
8
+ # * a stands for public api changes
9
+ # * b stands for private api changes
10
+ # * c stands for patch changes (not touching public or private api)
11
+ VERSION = '0.2.0.0'
12
12
  end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: verifly
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.0
4
+ version: 0.2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Smirnov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-04-03 00:00:00.000000000 Z
11
+ date: 2017-04-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '0.10'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: '0.10'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -150,7 +150,7 @@ dependencies:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
152
  version: '1.1'
153
- description: ''
153
+ description: 'See more info at http://www.rubydoc.info/gems/verifly/0.2.0.0 '
154
154
  email:
155
155
  - begdory4@gmail.com
156
156
  executables: []
@@ -162,10 +162,10 @@ files:
162
162
  - lib/verifly/applicator_with_options.rb
163
163
  - lib/verifly/class_builder.rb
164
164
  - lib/verifly/verifier.rb
165
- - lib/verifly/verifier/applicator_with_options_builder.rb
166
165
  - lib/verifly/version.rb
167
- homepage: http://example.com
168
- licenses: []
166
+ homepage: https://github.com/umbrellio/verifly
167
+ licenses:
168
+ - MIT
169
169
  metadata: {}
170
170
  post_install_message:
171
171
  rdoc_options: []
@@ -173,9 +173,9 @@ require_paths:
173
173
  - lib
174
174
  required_ruby_version: !ruby/object:Gem::Requirement
175
175
  requirements:
176
- - - ">="
176
+ - - "~>"
177
177
  - !ruby/object:Gem::Version
178
- version: '0'
178
+ version: '2.3'
179
179
  required_rubygems_version: !ruby/object:Gem::Requirement
180
180
  requirements:
181
181
  - - ">="
@@ -186,5 +186,6 @@ rubyforge_project:
186
186
  rubygems_version: 2.5.2
187
187
  signing_key:
188
188
  specification_version: 4
189
- summary: ''
189
+ summary: An api to run sequential checks like 'ActiveModel::Validations' do, but with
190
+ generic messages instead of errors
190
191
  test_files: []
@@ -1,74 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Verifly
4
- class Verifier
5
- # Builds ApplicatorWithOptions from different invocation styles.
6
- # @api private
7
- # @attr base [Class]
8
- # class for which applicator_with_options should be built
9
- # @attr args [Array]
10
- # array of arguments Verifier.verify invoked with
11
- # @attr block [Proc]
12
- # block Verifier.verify invoked with
13
- ApplicatorWithOptionsBuilder = Struct.new(:base, :args, :block)
14
- class ApplicatorWithOptionsBuilder
15
- # @!method self.call(base)
16
- # transforms `verify` arguments to class attributes
17
- # and invokes calculation
18
- # @raise [ArgumentError]
19
- # @return [ApplicatorWithOptions] resulting applicator_with_options
20
- def self.call(base, *args, &block)
21
- new(base, args, block).call
22
- end
23
-
24
- # Tries different invocation styles until one matches
25
- # @see #try_block
26
- # @see #try_nesting
27
- # @see #default
28
- # @raise [ArgumentError]
29
- # @return [ApplicatorWithOptions] resulting applicator_with_options
30
- def call
31
- try_block || try_nesting || default
32
- end
33
-
34
- private
35
-
36
- # @example with options
37
- # verify(if: true) { ... }
38
- # @example without options
39
- # verify { ... }
40
- # @return [ApplicatorWithOptions]
41
- def try_block
42
- ApplicatorWithOptions.new(block, *args) if block
43
- end
44
-
45
- # @example correct
46
- # verify SubVerifier
47
- # @example incorrect
48
- # verify Class
49
- # @raise [ArgumentError]
50
- # @return [ApplicatorWithOptions]
51
- def try_nesting
52
- verifier, *rest = args
53
- return unless verifier.is_a?(Class)
54
- raise ArgumentError, <<~ERROR unless verifier < base
55
- Nested verifiers should be inherited from verifier they nested are in
56
- ERROR
57
-
58
- applicable = lambda do |context|
59
- messages.concat(verifier.call(model, context))
60
- end
61
-
62
- ApplicatorWithOptions.new(applicable, *rest)
63
- end
64
-
65
- # Simply passes args to ApplicatorWithOptions
66
- # @example
67
- # verify(:foo, unless: false)
68
- # @return [ApplicatorWithOptions]
69
- def default
70
- ApplicatorWithOptions.new(*args)
71
- end
72
- end
73
- end
74
- end