verifly 0.1.0.0 → 0.2.0.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 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