rest_my_case 1.7.0 → 1.7.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +0 -1
- data/lib/rest_my_case/{validator → accusation_attorneys}/errors.rb +1 -1
- data/lib/rest_my_case/accusation_attorneys/format.rb +60 -0
- data/lib/rest_my_case/accusation_attorneys/length.rb +82 -0
- data/lib/rest_my_case/accusation_attorneys/numericality.rb +90 -0
- data/lib/rest_my_case/config/base.rb +2 -1
- data/lib/rest_my_case/config/general.rb +1 -0
- data/lib/rest_my_case/defense_attorney/base.rb +18 -19
- data/lib/rest_my_case/trial/case.rb +7 -9
- data/lib/rest_my_case/validator.rb +144 -0
- data/lib/rest_my_case/version.rb +1 -1
- data/lib/rest_my_case.rb +3 -5
- data/spec/rest_my_case/base_spec.rb +61 -47
- data/spec/rest_my_case/defense_attorney/base_spec.rb +69 -7
- data/spec/support/defense_attorney.rb +11 -1
- data/spec/support/perform.rb +7 -1
- data/spec/support/validator/usecases/hierarchy_validation.rb +1 -1
- metadata +7 -5
- data/lib/rest_my_case/validator/base.rb +0 -82
- data/lib/rest_my_case/validator/class_methods.rb +0 -58
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4686d3176a531d96c52e66d6b2b512746a102762
|
4
|
+
data.tar.gz: d1c4f92042481db02d456e7ffecc42f40d813557
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 308e0eb453f14fa551d35a41a8ea93a95211ef34497be4a101ac05b60a87fff2e5bf90063a5a8af05943c5e286310cad7a1696ca39b84dca5286ae020a696faa
|
7
|
+
data.tar.gz: c6eb0b3bc987c0b66e713ddffbdf6b831eec559bd678444d278be3551b5c0a41d9ca7eabaf85350ec0cd0c04fed7271077d3bd00ffa3d44757bda70e39d508d2
|
data/.rubocop.yml
CHANGED
@@ -0,0 +1,60 @@
|
|
1
|
+
module RestMyCase
|
2
|
+
module AccusationAttorneys
|
3
|
+
|
4
|
+
class Format < Each
|
5
|
+
def validate_each(record, attribute, value)
|
6
|
+
if options[:with]
|
7
|
+
regexp = option_call(record, :with)
|
8
|
+
record_error(record, attribute, :with, value) if value.to_s !~ regexp
|
9
|
+
elsif options[:without]
|
10
|
+
regexp = option_call(record, :without)
|
11
|
+
record_error(record, attribute, :without, value) if value.to_s =~ regexp
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def check_validity!
|
16
|
+
unless options.include?(:with) ^ options.include?(:without) # ^ == xor, or "exclusive or"
|
17
|
+
raise ArgumentError, "Either :with or :without must be supplied (but not both)"
|
18
|
+
end
|
19
|
+
|
20
|
+
check_options_validity(options, :with)
|
21
|
+
check_options_validity(options, :without)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def option_call(record, name)
|
27
|
+
option = options[name]
|
28
|
+
option.respond_to?(:call) ? option.call(record) : option
|
29
|
+
end
|
30
|
+
|
31
|
+
def record_error(record, attribute, name, value)
|
32
|
+
record.errors.add(attribute, :invalid, Helpers.except(options, name).merge!(value: value))
|
33
|
+
end
|
34
|
+
|
35
|
+
def regexp_using_multiline_anchors?(regexp)
|
36
|
+
regexp.source.start_with?("^") ||
|
37
|
+
(regexp.source.end_with?("$") && !regexp.source.end_with?("\\$"))
|
38
|
+
end
|
39
|
+
|
40
|
+
def check_options_validity(options, name)
|
41
|
+
option = options[name]
|
42
|
+
if option && !option.is_a?(Regexp) && !option.respond_to?(:call)
|
43
|
+
raise ArgumentError, "A regular expression or a proc or lambda must be supplied as :#{name}"
|
44
|
+
elsif option && option.is_a?(Regexp) &&
|
45
|
+
regexp_using_multiline_anchors?(option) && options[:multiline] != true
|
46
|
+
raise ArgumentError, "The provided regular expression is using multiline anchors (^ or $), " \
|
47
|
+
"which may present a security risk. Did you mean to use \\A and \\z, or forgot to add the " \
|
48
|
+
":multiline => true option?"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
module HelperMethods
|
54
|
+
def validates_format_of(*attr_names)
|
55
|
+
validates_with Format, _merge_attributes(attr_names)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module RestMyCase
|
2
|
+
module AccusationAttorneys
|
3
|
+
|
4
|
+
class Length < Each
|
5
|
+
MESSAGES = { is: :wrong_length, minimum: :too_short, maximum: :too_long }.freeze
|
6
|
+
CHECKS = { is: :==, minimum: :>=, maximum: :<= }.freeze
|
7
|
+
|
8
|
+
RESERVED_OPTIONS = [:minimum, :maximum, :within, :is, :tokenizer, :too_short, :too_long]
|
9
|
+
|
10
|
+
def initialize(options)
|
11
|
+
if range = (options.delete(:in) || options.delete(:within))
|
12
|
+
raise ArgumentError, ":in and :within must be a Range" unless range.is_a?(Range)
|
13
|
+
options[:minimum], options[:maximum] = range.min, range.max
|
14
|
+
end
|
15
|
+
|
16
|
+
if options[:allow_blank] == false && options[:minimum].nil? && options[:is].nil?
|
17
|
+
options[:minimum] = 1
|
18
|
+
end
|
19
|
+
|
20
|
+
super
|
21
|
+
end
|
22
|
+
|
23
|
+
def check_validity!
|
24
|
+
keys = CHECKS.keys & options.keys
|
25
|
+
|
26
|
+
if keys.empty?
|
27
|
+
raise ArgumentError, 'Range unspecified. Specify the :in, :within, :maximum, :minimum, or :is option.'
|
28
|
+
end
|
29
|
+
|
30
|
+
keys.each do |key|
|
31
|
+
value = options[key]
|
32
|
+
|
33
|
+
unless (value.is_a?(Integer) && value >= 0) || value == Float::INFINITY
|
34
|
+
raise ArgumentError, ":#{key} must be a nonnegative Integer or Infinity"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def validate_each(record, attribute, value)
|
40
|
+
value = tokenize(value)
|
41
|
+
value_length = value.respond_to?(:length) ? value.length : value.to_s.length
|
42
|
+
errors_options = Helpers.except(options, *RESERVED_OPTIONS)
|
43
|
+
|
44
|
+
CHECKS.each do |key, validity_check|
|
45
|
+
next unless check_value = options[key]
|
46
|
+
|
47
|
+
if !value.nil? || skip_nil_check?(key)
|
48
|
+
next if value_length.send(validity_check, check_value)
|
49
|
+
end
|
50
|
+
|
51
|
+
errors_options[:count] = check_value
|
52
|
+
|
53
|
+
default_message = options[MESSAGES[key]]
|
54
|
+
errors_options[:message] ||= default_message if default_message
|
55
|
+
|
56
|
+
record.errors.add(attribute, MESSAGES[key], errors_options)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def tokenize(value)
|
63
|
+
if options[:tokenizer] && value.kind_of?(String)
|
64
|
+
options[:tokenizer].call(value)
|
65
|
+
end || value
|
66
|
+
end
|
67
|
+
|
68
|
+
def skip_nil_check?(key)
|
69
|
+
key == :maximum && options[:allow_nil].nil? && options[:allow_blank].nil?
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
module HelperMethods
|
74
|
+
def validates_length_of(*attr_names)
|
75
|
+
validates_with Length, _merge_attributes(attr_names)
|
76
|
+
end
|
77
|
+
|
78
|
+
alias_method :validates_size_of, :validates_length_of
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module RestMyCase
|
2
|
+
module AccusationAttorneys
|
3
|
+
|
4
|
+
class Numericality < Each
|
5
|
+
CHECKS = { :greater_than => :>, :greater_than_or_equal_to => :>=,
|
6
|
+
:equal_to => :==, :less_than => :<, :less_than_or_equal_to => :<=,
|
7
|
+
:odd => :odd?, :even => :even? }.freeze
|
8
|
+
|
9
|
+
RESERVED_OPTIONS = CHECKS.keys + [:only_integer]
|
10
|
+
|
11
|
+
def check_validity!
|
12
|
+
keys = CHECKS.keys - [:odd, :even]
|
13
|
+
|
14
|
+
Helpers.slice(options, *keys).each do |option, value|
|
15
|
+
next if value.nil? || value.is_a?(Numeric) || value.is_a?(Proc) || value.is_a?(Symbol)
|
16
|
+
raise ArgumentError, ":#{option} must be a number, a symbol or a proc"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def validate_each(record, attr_name, value)
|
21
|
+
before_type_cast = "#{attr_name}_before_type_cast"
|
22
|
+
|
23
|
+
raw_value = record.send(before_type_cast) if record.respond_to?(before_type_cast.to_sym)
|
24
|
+
raw_value ||= value
|
25
|
+
|
26
|
+
return if options[:allow_nil] && raw_value.nil?
|
27
|
+
|
28
|
+
unless value = parse_raw_value_as_a_number(raw_value)
|
29
|
+
record.errors.add(attr_name, :not_a_number, filtered_options(raw_value))
|
30
|
+
return
|
31
|
+
end
|
32
|
+
|
33
|
+
if options[:only_integer]
|
34
|
+
unless value = parse_raw_value_as_an_integer(raw_value)
|
35
|
+
record.errors.add(attr_name, :not_an_integer, filtered_options(raw_value))
|
36
|
+
return
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
Helpers.slice(options, *CHECKS.keys).each do |option, option_value|
|
41
|
+
next if option_value.nil?
|
42
|
+
|
43
|
+
case option
|
44
|
+
when :odd, :even
|
45
|
+
unless value.to_i.send(CHECKS[option])
|
46
|
+
record.errors.add(attr_name, option, filtered_options(value))
|
47
|
+
end
|
48
|
+
else
|
49
|
+
option_value = option_value.call(record) if option_value.is_a?(Proc)
|
50
|
+
option_value = record.send(option_value) if option_value.is_a?(Symbol)
|
51
|
+
|
52
|
+
unless value.send(CHECKS[option], option_value)
|
53
|
+
record.errors.add(attr_name, option, filtered_options(value).merge(:count => option_value))
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
protected
|
60
|
+
|
61
|
+
def parse_raw_value_as_a_number(raw_value)
|
62
|
+
case raw_value
|
63
|
+
when /\A0[xX]/
|
64
|
+
nil
|
65
|
+
else
|
66
|
+
begin
|
67
|
+
Kernel.Float(raw_value)
|
68
|
+
rescue ArgumentError, TypeError
|
69
|
+
nil
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def parse_raw_value_as_an_integer(raw_value)
|
75
|
+
raw_value.to_i if raw_value.to_s =~ /\A[+-]?\d+\Z/
|
76
|
+
end
|
77
|
+
|
78
|
+
def filtered_options(value)
|
79
|
+
Helpers.except(options, *RESERVED_OPTIONS).merge!(:value => value)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
module HelperMethods
|
84
|
+
def validates_numericality_of(*attr_names)
|
85
|
+
validates_with Numericality, _merge_attributes(attr_names)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
@@ -4,36 +4,35 @@ module RestMyCase
|
|
4
4
|
class Base
|
5
5
|
|
6
6
|
def initialize(trial_case)
|
7
|
-
@trial_case
|
7
|
+
@trial_case = trial_case
|
8
|
+
@trial_case.use_cases = []
|
8
9
|
end
|
9
10
|
|
10
11
|
def build_case_for_the_defendant
|
11
|
-
@trial_case.
|
12
|
-
@trial_case.
|
13
|
-
|
14
|
-
end.flatten
|
12
|
+
dependencies(@trial_case.defendant_class).map do |dependency|
|
13
|
+
gather_all_use_cases dependency, @trial_case.defendant
|
14
|
+
end
|
15
15
|
end
|
16
16
|
|
17
17
|
protected ######################## PROTECTED #############################
|
18
18
|
|
19
|
-
def
|
20
|
-
|
21
|
-
|
22
|
-
all_dependencies(use_case_class.superclass) |
|
23
|
-
dependencies_including_itself(use_case_class, @trial_case.defendant)
|
24
|
-
end
|
25
|
-
|
26
|
-
private ########################### PRIVATE ##############################
|
19
|
+
def gather_all_use_cases(use_case_class, dependent)
|
20
|
+
use_case = use_case_class.new(@trial_case.context, dependent)
|
27
21
|
|
28
|
-
|
29
|
-
|
22
|
+
dependencies(use_case_class).map do |dependency|
|
23
|
+
gather_all_use_cases dependency, use_case
|
24
|
+
end
|
30
25
|
|
31
|
-
|
26
|
+
@trial_case.use_cases.push use_case
|
32
27
|
end
|
33
28
|
|
34
|
-
def dependencies(
|
35
|
-
|
36
|
-
|
29
|
+
def dependencies(use_case_class)
|
30
|
+
return [] if use_case_class == @trial_case.last_ancestor
|
31
|
+
|
32
|
+
if RestMyCase.get_config :parent_dependencies_first, use_case_class
|
33
|
+
dependencies(use_case_class.superclass) | use_case_class.dependencies
|
34
|
+
else
|
35
|
+
use_case_class.dependencies | dependencies(use_case_class.superclass)
|
37
36
|
end
|
38
37
|
end
|
39
38
|
|
@@ -5,13 +5,13 @@ module RestMyCase
|
|
5
5
|
|
6
6
|
attr_accessor :use_cases, :should_abort
|
7
7
|
|
8
|
-
attr_reader :context, :defendant, :last_ancestor, :
|
8
|
+
attr_reader :context, :defendant, :last_ancestor, :defendant_class
|
9
9
|
|
10
10
|
def initialize(last_ancestor, use_case_classes, attributes)
|
11
|
-
@context
|
12
|
-
@
|
13
|
-
@
|
14
|
-
@
|
11
|
+
@context = build_context attributes
|
12
|
+
@last_ancestor = last_ancestor
|
13
|
+
@defendant_class = build_defendant(last_ancestor, use_case_classes)
|
14
|
+
@defendant = @defendant_class.new @context
|
15
15
|
end
|
16
16
|
|
17
17
|
def aborted
|
@@ -26,10 +26,8 @@ module RestMyCase
|
|
26
26
|
Context::Base.new attributes
|
27
27
|
end
|
28
28
|
|
29
|
-
def build_defendant(
|
30
|
-
Class.new(
|
31
|
-
depends(*use_case_classes)
|
32
|
-
end.new(@context)
|
29
|
+
def build_defendant(last_ancestor, use_case_classes)
|
30
|
+
Class.new(last_ancestor) { depends(*use_case_classes) }
|
33
31
|
end
|
34
32
|
|
35
33
|
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
module RestMyCase
|
2
|
+
|
3
|
+
class Validator < RestMyCase::Base
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
|
7
|
+
attr_writer :validators
|
8
|
+
|
9
|
+
attr_reader :clear_errors
|
10
|
+
|
11
|
+
def trial_court
|
12
|
+
@trial_court ||= Trial::Court.new \
|
13
|
+
Judge::Base, DefenseAttorney::Base, RestMyCase::Validator
|
14
|
+
end
|
15
|
+
|
16
|
+
def target_name
|
17
|
+
@target_name || Helpers.super_method(self, :target_name)
|
18
|
+
end
|
19
|
+
|
20
|
+
def target(target_name)
|
21
|
+
@target_name = target_name
|
22
|
+
end
|
23
|
+
|
24
|
+
def clear_errors!
|
25
|
+
@clear_errors = true
|
26
|
+
end
|
27
|
+
|
28
|
+
def validators
|
29
|
+
@validators ||= Hash.new { |hash, key| hash[key] = [] }
|
30
|
+
end
|
31
|
+
|
32
|
+
def validate(*args, &block)
|
33
|
+
validators[nil] << CustomValidator.new(args, &block)
|
34
|
+
end
|
35
|
+
|
36
|
+
def validates_with(*args, &block)
|
37
|
+
options = Helpers.extract_options!(args)
|
38
|
+
|
39
|
+
options[:class] = self
|
40
|
+
|
41
|
+
args.each do |klass|
|
42
|
+
store_validators_by_attribute klass.new(options, &block)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
protected ######################## PROTECTED #############################
|
47
|
+
|
48
|
+
def store_validators_by_attribute(validator)
|
49
|
+
if validator.respond_to?(:attributes) && !validator.attributes.empty?
|
50
|
+
validator.attributes.each do |attribute|
|
51
|
+
validators[attribute.to_sym] << validator
|
52
|
+
end
|
53
|
+
else
|
54
|
+
validators[nil] << validator
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Copy validators on inheritance.
|
59
|
+
def inherited(base)
|
60
|
+
dup = validators.dup
|
61
|
+
base.validators = dup.each { |k, v| dup[k] = v.dup }
|
62
|
+
super
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
######################## INSTANCE METHODS BELLOW ###########################
|
68
|
+
|
69
|
+
extend ClassMethods
|
70
|
+
|
71
|
+
self.silence_dependencies_abort = true
|
72
|
+
|
73
|
+
extend AccusationAttorneys::HelperMethods
|
74
|
+
|
75
|
+
def target_name
|
76
|
+
self.class.target_name
|
77
|
+
end
|
78
|
+
|
79
|
+
def target
|
80
|
+
respond_to?(target_name) ? send(target_name) : context.send(target_name)
|
81
|
+
end
|
82
|
+
|
83
|
+
def perform
|
84
|
+
targets = [*target]
|
85
|
+
|
86
|
+
skip! if targets.empty?
|
87
|
+
|
88
|
+
if target.nil?
|
89
|
+
error('no target to validate!')
|
90
|
+
else
|
91
|
+
error('unprocessable_entity') unless all_validations_green? targets
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
protected ######################## PROTECTED ###############################
|
96
|
+
|
97
|
+
def all_validations_green?(targets)
|
98
|
+
targets.map do |object_to_validate|
|
99
|
+
if Helpers.marked_for_destruction?(object_to_validate)
|
100
|
+
true
|
101
|
+
else
|
102
|
+
extend_errors_and_run_validations(object_to_validate)
|
103
|
+
|
104
|
+
object_to_validate.errors.empty?
|
105
|
+
end
|
106
|
+
end.all?
|
107
|
+
end
|
108
|
+
|
109
|
+
private ########################### PRIVATE ################################
|
110
|
+
|
111
|
+
def extend_errors_and_run_validations(object_to_validate)
|
112
|
+
extend_errors_if_necessary object_to_validate
|
113
|
+
|
114
|
+
object_to_validate.errors.clear if self.class.clear_errors
|
115
|
+
|
116
|
+
self.class.validators.values.flatten.uniq.each do |validator|
|
117
|
+
next if validator_condition_fails(validator, object_to_validate)
|
118
|
+
|
119
|
+
validator.base = self
|
120
|
+
|
121
|
+
validator.validate object_to_validate
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def extend_errors_if_necessary(object_to_validate)
|
126
|
+
return true if object_to_validate.respond_to?(:errors)
|
127
|
+
|
128
|
+
object_to_validate.instance_eval do
|
129
|
+
def errors
|
130
|
+
@errors ||= AccusationAttorneys::Errors.new(self)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def validator_condition_fails(validator, object_to_validate)
|
136
|
+
return false unless validator.options.key?(:if)
|
137
|
+
|
138
|
+
!Helpers.call_proc_or_method \
|
139
|
+
self, validator.options[:if], object_to_validate
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
data/lib/rest_my_case/version.rb
CHANGED
data/lib/rest_my_case.rb
CHANGED
@@ -11,20 +11,18 @@ require 'rest_my_case/judge/base'
|
|
11
11
|
require 'rest_my_case/trial/case'
|
12
12
|
require 'rest_my_case/trial/court'
|
13
13
|
|
14
|
-
require 'rest_my_case/base'
|
15
|
-
|
16
14
|
require 'rest_my_case/accusation_attorneys/helper_methods'
|
17
15
|
require 'rest_my_case/accusation_attorneys/base'
|
18
16
|
require 'rest_my_case/accusation_attorneys/each'
|
19
17
|
require 'rest_my_case/accusation_attorneys/custom'
|
18
|
+
require 'rest_my_case/accusation_attorneys/errors'
|
20
19
|
# require 'rest_my_case/accusation_attorneys/format'
|
21
20
|
# require 'rest_my_case/accusation_attorneys/length'
|
22
21
|
require 'rest_my_case/accusation_attorneys/presence'
|
23
22
|
# require 'rest_my_case/accusation_attorneys/numericality'
|
24
23
|
|
25
|
-
require 'rest_my_case/
|
26
|
-
require 'rest_my_case/validator
|
27
|
-
require 'rest_my_case/validator/base'
|
24
|
+
require 'rest_my_case/base'
|
25
|
+
require 'rest_my_case/validator'
|
28
26
|
|
29
27
|
module RestMyCase
|
30
28
|
|
@@ -111,10 +111,10 @@ describe RestMyCase::Base do
|
|
111
111
|
end
|
112
112
|
|
113
113
|
it "context prove that only the correct method have ran" do
|
114
|
-
expect(@context.setup.length).to be
|
114
|
+
expect(@context.setup.length).to be 4
|
115
115
|
expect(@context.perform.length).to be 0
|
116
116
|
expect(@context.rollback.length).to be 0
|
117
|
-
expect(@context.final.length).to be
|
117
|
+
expect(@context.final.length).to be 12
|
118
118
|
end
|
119
119
|
end
|
120
120
|
|
@@ -133,10 +133,10 @@ describe RestMyCase::Base do
|
|
133
133
|
end
|
134
134
|
|
135
135
|
it "context prove that only the correct method have ran" do
|
136
|
-
expect(@context.setup.length).to be
|
136
|
+
expect(@context.setup.length).to be 3
|
137
137
|
expect(@context.perform.length).to be 0
|
138
138
|
expect(@context.rollback.length).to be 0
|
139
|
-
expect(@context.final.length).to be
|
139
|
+
expect(@context.final.length).to be 12
|
140
140
|
end
|
141
141
|
end
|
142
142
|
|
@@ -151,10 +151,10 @@ describe RestMyCase::Base do
|
|
151
151
|
end
|
152
152
|
|
153
153
|
it "context prove that only the correct method have ran" do
|
154
|
-
expect(@context.setup.length).to be
|
154
|
+
expect(@context.setup.length).to be 3
|
155
155
|
expect(@context.perform.length).to be 0
|
156
156
|
expect(@context.rollback.length).to be 0
|
157
|
-
expect(@context.final.length).to be
|
157
|
+
expect(@context.final.length).to be 12
|
158
158
|
end
|
159
159
|
end
|
160
160
|
|
@@ -169,10 +169,10 @@ describe RestMyCase::Base do
|
|
169
169
|
end
|
170
170
|
|
171
171
|
it "context prove that only the correct method have ran" do
|
172
|
-
expect(@context.setup.length).to be
|
173
|
-
expect(@context.perform.length).to be
|
174
|
-
expect(@context.rollback.length).to be
|
175
|
-
expect(@context.final.length).to be
|
172
|
+
expect(@context.setup.length).to be 12
|
173
|
+
expect(@context.perform.length).to be 3
|
174
|
+
expect(@context.rollback.length).to be 4
|
175
|
+
expect(@context.final.length).to be 12
|
176
176
|
end
|
177
177
|
end
|
178
178
|
|
@@ -187,10 +187,10 @@ describe RestMyCase::Base do
|
|
187
187
|
end
|
188
188
|
|
189
189
|
it "context prove that only the correct method have ran" do
|
190
|
-
expect(@context.setup.length).to be
|
191
|
-
expect(@context.perform.length).to be
|
190
|
+
expect(@context.setup.length).to be 12
|
191
|
+
expect(@context.perform.length).to be 11
|
192
192
|
expect(@context.rollback.length).to be 0
|
193
|
-
expect(@context.final.length).to be
|
193
|
+
expect(@context.final.length).to be 12
|
194
194
|
end
|
195
195
|
end
|
196
196
|
|
@@ -206,10 +206,10 @@ describe RestMyCase::Base do
|
|
206
206
|
end
|
207
207
|
|
208
208
|
it "context prove that only the correct method have ran" do
|
209
|
-
expect(@context.setup.length).to be
|
210
|
-
expect(@context.perform.length).to be
|
209
|
+
expect(@context.setup.length).to be 11
|
210
|
+
expect(@context.perform.length).to be 11
|
211
211
|
expect(@context.rollback.length).to be 0
|
212
|
-
expect(@context.final.length).to be
|
212
|
+
expect(@context.final.length).to be 12
|
213
213
|
end
|
214
214
|
|
215
215
|
end
|
@@ -234,10 +234,10 @@ describe RestMyCase::Base do
|
|
234
234
|
end
|
235
235
|
|
236
236
|
it "context prove that only the correct method have ran" do
|
237
|
-
expect(@context.setup.length).to be
|
237
|
+
expect(@context.setup.length).to be 8
|
238
238
|
expect(@context.perform.length).to be 0
|
239
239
|
expect(@context.rollback.length).to be 0
|
240
|
-
expect(@context.final.length).to be
|
240
|
+
expect(@context.final.length).to be 12
|
241
241
|
end
|
242
242
|
|
243
243
|
end
|
@@ -258,10 +258,10 @@ describe RestMyCase::Base do
|
|
258
258
|
end
|
259
259
|
|
260
260
|
it "context prove that only the correct method have ran" do
|
261
|
-
expect(@context.setup.length).to be
|
262
|
-
expect(@context.perform.length).to be
|
263
|
-
expect(@context.rollback.length).to be
|
264
|
-
expect(@context.final.length).to be
|
261
|
+
expect(@context.setup.length).to be 12
|
262
|
+
expect(@context.perform.length).to be 8
|
263
|
+
expect(@context.rollback.length).to be 8
|
264
|
+
expect(@context.final.length).to be 12
|
265
265
|
end
|
266
266
|
|
267
267
|
end
|
@@ -293,10 +293,10 @@ describe RestMyCase::Base do
|
|
293
293
|
end
|
294
294
|
|
295
295
|
it "context prove that only the correct method have ran" do
|
296
|
-
expect(@context.setup.length).to be
|
297
|
-
expect(@context.perform.length).to be
|
296
|
+
expect(@context.setup.length).to be 12
|
297
|
+
expect(@context.perform.length).to be 12
|
298
298
|
expect(@context.rollback.length).to be 0
|
299
|
-
expect(@context.final.length).to be
|
299
|
+
expect(@context.final.length).to be 12
|
300
300
|
end
|
301
301
|
|
302
302
|
end
|
@@ -340,40 +340,46 @@ describe RestMyCase::Base do
|
|
340
340
|
@context = Perform::ScreammingInvoker.perform
|
341
341
|
|
342
342
|
expect(@context.setup).to eq [
|
343
|
-
"Perform::
|
343
|
+
"Perform::Logger",
|
344
344
|
"Perform::ScreammingInvoker",
|
345
|
-
"Perform::
|
345
|
+
"Perform::Logger",
|
346
346
|
"Perform::BuildPost",
|
347
|
-
"Perform::
|
347
|
+
"Perform::Logger",
|
348
348
|
"Perform::ValidateName",
|
349
|
+
"Perform::Logger",
|
349
350
|
"Perform::ValidateBody",
|
351
|
+
"Perform::Logger",
|
350
352
|
"Perform::Validations",
|
351
|
-
"Perform::
|
353
|
+
"Perform::Logger",
|
352
354
|
"Perform::SavePost"
|
353
355
|
]
|
354
356
|
expect(@context.perform).to eq [
|
355
|
-
"Perform::
|
357
|
+
"Perform::Logger",
|
356
358
|
"Perform::ScreammingInvoker",
|
357
|
-
"Perform::
|
359
|
+
"Perform::Logger",
|
358
360
|
"Perform::BuildPost",
|
359
|
-
"Perform::
|
361
|
+
"Perform::Logger",
|
360
362
|
"Perform::ValidateName",
|
363
|
+
"Perform::Logger",
|
361
364
|
"Perform::ValidateBody",
|
365
|
+
"Perform::Logger",
|
362
366
|
"Perform::Validations",
|
363
|
-
"Perform::
|
367
|
+
"Perform::Logger",
|
364
368
|
"Perform::SavePost"
|
365
369
|
]
|
366
370
|
expect(@context.rollback).to eq []
|
367
371
|
expect(@context.final).to eq [
|
368
|
-
"Perform::
|
372
|
+
"Perform::Logger",
|
369
373
|
"Perform::BuildPost",
|
370
|
-
"Perform::
|
374
|
+
"Perform::Logger",
|
371
375
|
"Perform::ValidateName",
|
376
|
+
"Perform::Logger",
|
372
377
|
"Perform::ValidateBody",
|
378
|
+
"Perform::Logger",
|
373
379
|
"Perform::Validations",
|
374
|
-
"Perform::
|
380
|
+
"Perform::Logger",
|
375
381
|
"Perform::SavePost",
|
376
|
-
"Perform::
|
382
|
+
"Perform::Logger",
|
377
383
|
"Perform::ScreammingInvoker"
|
378
384
|
]
|
379
385
|
end
|
@@ -401,39 +407,47 @@ describe RestMyCase::Base do
|
|
401
407
|
|
402
408
|
it "invoker should abort the process it his invokees have also aborted" do
|
403
409
|
expect(@context.setup).to eq [
|
404
|
-
"Perform::
|
410
|
+
"Perform::Logger",
|
405
411
|
"Perform::BuildPost",
|
412
|
+
"Perform::Logger",
|
406
413
|
"Perform::Validations2",
|
414
|
+
"Perform::Logger",
|
407
415
|
"Perform::SavePost",
|
416
|
+
"Perform::Logger",
|
408
417
|
"Perform::CreatePost2",
|
409
|
-
"Perform::
|
418
|
+
"Perform::Logger",
|
410
419
|
"Perform::ValidateName",
|
411
|
-
"Perform::
|
420
|
+
"Perform::Logger",
|
412
421
|
"Perform::ValidateBody"
|
413
422
|
]
|
414
423
|
expect(@context.perform).to eq [
|
415
|
-
"Perform::
|
424
|
+
"Perform::Logger",
|
416
425
|
"Perform::BuildPost",
|
426
|
+
"Perform::Logger",
|
417
427
|
"Perform::Validations2",
|
418
|
-
"Perform::
|
428
|
+
"Perform::Logger",
|
419
429
|
"Perform::ValidateName"
|
420
430
|
]
|
421
431
|
expect(@context.rollback).to eq [
|
422
432
|
"Perform::ValidateName",
|
423
|
-
"Perform::
|
433
|
+
"Perform::Logger",
|
424
434
|
"Perform::Validations2",
|
435
|
+
"Perform::Logger",
|
425
436
|
"Perform::BuildPost",
|
426
|
-
"Perform::
|
437
|
+
"Perform::Logger"
|
427
438
|
]
|
428
439
|
expect(@context.final).to eq [
|
429
|
-
"Perform::
|
440
|
+
"Perform::Logger",
|
430
441
|
"Perform::ValidateName",
|
431
|
-
"Perform::
|
442
|
+
"Perform::Logger",
|
432
443
|
"Perform::ValidateBody",
|
433
|
-
"Perform::
|
444
|
+
"Perform::Logger",
|
434
445
|
"Perform::BuildPost",
|
446
|
+
"Perform::Logger",
|
435
447
|
"Perform::Validations2",
|
448
|
+
"Perform::Logger",
|
436
449
|
"Perform::SavePost",
|
450
|
+
"Perform::Logger",
|
437
451
|
"Perform::CreatePost2"
|
438
452
|
]
|
439
453
|
end
|
@@ -48,21 +48,83 @@ describe RestMyCase::DefenseAttorney::Base do
|
|
48
48
|
let(:use_case_classes) { [DefenseAttorney::CreatePostWithComments] }
|
49
49
|
|
50
50
|
it_behaves_like "a porper shepherd", [
|
51
|
+
DefenseAttorney::BuildComments,
|
52
|
+
DefenseAttorney::SaveComments,
|
53
|
+
DefenseAttorney::CreateComments,
|
54
|
+
DefenseAttorney::AssignAttributes,
|
55
|
+
DefenseAttorney::BuildSomething,
|
56
|
+
DefenseAttorney::BuildPost,
|
57
|
+
DefenseAttorney::SavePost,
|
51
58
|
DefenseAttorney::BuilEvent,
|
52
59
|
DefenseAttorney::SaveEvent,
|
53
60
|
DefenseAttorney::CreateEvent,
|
54
61
|
DefenseAttorney::LogEvents,
|
55
62
|
DefenseAttorney::AnalyseEvents,
|
56
|
-
DefenseAttorney::UseCaseWrapper,
|
57
|
-
DefenseAttorney::BuildPost,
|
58
|
-
DefenseAttorney::SavePost,
|
59
|
-
DefenseAttorney::CreatePost,
|
60
|
-
DefenseAttorney::BuildComments,
|
61
|
-
DefenseAttorney::SaveComments,
|
62
|
-
DefenseAttorney::CreateComments,
|
63
63
|
DefenseAttorney::CreatePostWithComments
|
64
64
|
]
|
65
65
|
|
66
66
|
end
|
67
67
|
|
68
|
+
context "When general config has parent_dependencies_first = true" do
|
69
|
+
|
70
|
+
before do
|
71
|
+
RestMyCase.configure do |config|
|
72
|
+
config.parent_dependencies_first = true
|
73
|
+
end
|
74
|
+
end
|
75
|
+
after { RestMyCase.reset_config }
|
76
|
+
|
77
|
+
context "When a use case inherits from another that also has dependencies" do
|
78
|
+
|
79
|
+
let(:use_case_classes) { [DefenseAttorney::CreatePostWithComments] }
|
80
|
+
|
81
|
+
it_behaves_like "a porper shepherd", [
|
82
|
+
DefenseAttorney::BuilEvent,
|
83
|
+
DefenseAttorney::SaveEvent,
|
84
|
+
DefenseAttorney::CreateEvent,
|
85
|
+
DefenseAttorney::LogEvents,
|
86
|
+
DefenseAttorney::AnalyseEvents,
|
87
|
+
DefenseAttorney::BuildSomething,
|
88
|
+
DefenseAttorney::AssignAttributes,
|
89
|
+
DefenseAttorney::BuildPost,
|
90
|
+
DefenseAttorney::SavePost,
|
91
|
+
DefenseAttorney::BuildComments,
|
92
|
+
DefenseAttorney::SaveComments,
|
93
|
+
DefenseAttorney::CreateComments,
|
94
|
+
DefenseAttorney::CreatePostWithComments
|
95
|
+
]
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
context "When dependent use_case has parent_dependencies_first = true" do
|
102
|
+
|
103
|
+
before { DefenseAttorney::BuildPost.parent_dependencies_first = true }
|
104
|
+
after { DefenseAttorney::BuildPost.parent_dependencies_first = nil }
|
105
|
+
|
106
|
+
context "When a use case inherits from another that also has dependencies" do
|
107
|
+
|
108
|
+
let(:use_case_classes) { [DefenseAttorney::CreatePostWithComments] }
|
109
|
+
|
110
|
+
it_behaves_like "a porper shepherd", [
|
111
|
+
DefenseAttorney::BuildComments,
|
112
|
+
DefenseAttorney::SaveComments,
|
113
|
+
DefenseAttorney::CreateComments,
|
114
|
+
DefenseAttorney::BuildSomething,
|
115
|
+
DefenseAttorney::AssignAttributes,
|
116
|
+
DefenseAttorney::BuildPost,
|
117
|
+
DefenseAttorney::SavePost,
|
118
|
+
DefenseAttorney::BuilEvent,
|
119
|
+
DefenseAttorney::SaveEvent,
|
120
|
+
DefenseAttorney::CreateEvent,
|
121
|
+
DefenseAttorney::LogEvents,
|
122
|
+
DefenseAttorney::AnalyseEvents,
|
123
|
+
DefenseAttorney::CreatePostWithComments
|
124
|
+
]
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
|
68
130
|
end
|
@@ -14,7 +14,17 @@ module DefenseAttorney
|
|
14
14
|
|
15
15
|
class AnalyseEvents < RestMyCase::Base; end
|
16
16
|
|
17
|
-
class
|
17
|
+
class BuildSomething < RestMyCase::Base; end
|
18
|
+
|
19
|
+
class AssignAttributes < RestMyCase::Base; end
|
20
|
+
|
21
|
+
class Builder < RestMyCase::Base
|
22
|
+
depends BuildSomething
|
23
|
+
end
|
24
|
+
|
25
|
+
class BuildPost < Builder
|
26
|
+
depends AssignAttributes
|
27
|
+
end
|
18
28
|
|
19
29
|
class SavePost < RestMyCase::Base; end
|
20
30
|
|
data/spec/support/perform.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Perform
|
2
2
|
|
3
|
-
class
|
3
|
+
class Test < RestMyCase::Base
|
4
4
|
def flow_control(method)
|
5
5
|
id = "#{self.class.name}_#{method}"
|
6
6
|
|
@@ -42,6 +42,12 @@ module Perform
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
+
class Logger < Test; end
|
46
|
+
|
47
|
+
class UseCaseWrapper < Test
|
48
|
+
depends Logger
|
49
|
+
end
|
50
|
+
|
45
51
|
class ValidateName < UseCaseWrapper; end
|
46
52
|
|
47
53
|
class ValidateBody < UseCaseWrapper; end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rest_my_case
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.7.
|
4
|
+
version: 1.7.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- goncalvesjoao
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-04-
|
11
|
+
date: 2015-04-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pry
|
@@ -115,7 +115,11 @@ files:
|
|
115
115
|
- lib/rest_my_case/accusation_attorneys/base.rb
|
116
116
|
- lib/rest_my_case/accusation_attorneys/custom.rb
|
117
117
|
- lib/rest_my_case/accusation_attorneys/each.rb
|
118
|
+
- lib/rest_my_case/accusation_attorneys/errors.rb
|
119
|
+
- lib/rest_my_case/accusation_attorneys/format.rb
|
118
120
|
- lib/rest_my_case/accusation_attorneys/helper_methods.rb
|
121
|
+
- lib/rest_my_case/accusation_attorneys/length.rb
|
122
|
+
- lib/rest_my_case/accusation_attorneys/numericality.rb
|
119
123
|
- lib/rest_my_case/accusation_attorneys/presence.rb
|
120
124
|
- lib/rest_my_case/base.rb
|
121
125
|
- lib/rest_my_case/config/base.rb
|
@@ -127,9 +131,7 @@ files:
|
|
127
131
|
- lib/rest_my_case/judge/base.rb
|
128
132
|
- lib/rest_my_case/trial/case.rb
|
129
133
|
- lib/rest_my_case/trial/court.rb
|
130
|
-
- lib/rest_my_case/validator
|
131
|
-
- lib/rest_my_case/validator/class_methods.rb
|
132
|
-
- lib/rest_my_case/validator/errors.rb
|
134
|
+
- lib/rest_my_case/validator.rb
|
133
135
|
- lib/rest_my_case/version.rb
|
134
136
|
- rest_my_case.gemspec
|
135
137
|
- spec/rest_my_case/base_spec.rb
|
@@ -1,82 +0,0 @@
|
|
1
|
-
module RestMyCase
|
2
|
-
module Validator
|
3
|
-
|
4
|
-
class Base < RestMyCase::Base
|
5
|
-
|
6
|
-
extend ClassMethods
|
7
|
-
|
8
|
-
self.silence_dependencies_abort = true
|
9
|
-
|
10
|
-
extend AccusationAttorneys::HelperMethods
|
11
|
-
|
12
|
-
def target_name
|
13
|
-
self.class.target_name
|
14
|
-
end
|
15
|
-
|
16
|
-
def target
|
17
|
-
respond_to?(target_name) ? send(target_name) : context.send(target_name)
|
18
|
-
end
|
19
|
-
|
20
|
-
def perform
|
21
|
-
targets = [*target]
|
22
|
-
|
23
|
-
skip! if targets.empty?
|
24
|
-
|
25
|
-
if target.nil?
|
26
|
-
error('no target to validate!')
|
27
|
-
else
|
28
|
-
error('unprocessable_entity') unless all_validations_green? targets
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
protected ######################## PROTECTED #############################
|
33
|
-
|
34
|
-
def all_validations_green?(targets)
|
35
|
-
targets.map do |object_to_validate|
|
36
|
-
if Helpers.marked_for_destruction?(object_to_validate)
|
37
|
-
true
|
38
|
-
else
|
39
|
-
extend_errors_and_run_validations(object_to_validate)
|
40
|
-
|
41
|
-
object_to_validate.errors.empty?
|
42
|
-
end
|
43
|
-
end.all?
|
44
|
-
end
|
45
|
-
|
46
|
-
private ########################### PRIVATE ##############################
|
47
|
-
|
48
|
-
def extend_errors_and_run_validations(object_to_validate)
|
49
|
-
extend_errors_if_necessary object_to_validate
|
50
|
-
|
51
|
-
object_to_validate.errors.clear if self.class.clear_errors
|
52
|
-
|
53
|
-
self.class.validators.values.flatten.uniq.each do |validator|
|
54
|
-
next if validator_condition_fails(validator, object_to_validate)
|
55
|
-
|
56
|
-
validator.base = self
|
57
|
-
|
58
|
-
validator.validate object_to_validate
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def extend_errors_if_necessary(object_to_validate)
|
63
|
-
return true if object_to_validate.respond_to?(:errors)
|
64
|
-
|
65
|
-
object_to_validate.instance_eval do
|
66
|
-
def errors
|
67
|
-
@errors ||= Errors.new(self)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def validator_condition_fails(validator, object_to_validate)
|
73
|
-
return false unless validator.options.key?(:if)
|
74
|
-
|
75
|
-
!Helpers.call_proc_or_method \
|
76
|
-
self, validator.options[:if], object_to_validate
|
77
|
-
end
|
78
|
-
|
79
|
-
end
|
80
|
-
|
81
|
-
end
|
82
|
-
end
|
@@ -1,58 +0,0 @@
|
|
1
|
-
module RestMyCase
|
2
|
-
module Validator
|
3
|
-
|
4
|
-
module ClassMethods
|
5
|
-
|
6
|
-
attr_reader :validators, :clear_errors
|
7
|
-
|
8
|
-
def trial_court
|
9
|
-
@trial_court ||= Trial::Court.new \
|
10
|
-
Judge::Base, DefenseAttorney::Base, RestMyCase::Validator::Base
|
11
|
-
end
|
12
|
-
|
13
|
-
def target_name
|
14
|
-
@target_name || Helpers.super_method(self, :target_name)
|
15
|
-
end
|
16
|
-
|
17
|
-
def target(target_name)
|
18
|
-
@target_name = target_name
|
19
|
-
end
|
20
|
-
|
21
|
-
def clear_errors!
|
22
|
-
@clear_errors = true
|
23
|
-
end
|
24
|
-
|
25
|
-
def validators
|
26
|
-
@validators ||= Hash.new { |hash, key| hash[key] = [] }
|
27
|
-
end
|
28
|
-
|
29
|
-
def validate(*args, &block)
|
30
|
-
validators[nil] << CustomValidator.new(args, &block)
|
31
|
-
end
|
32
|
-
|
33
|
-
def validates_with(*args, &block)
|
34
|
-
options = Helpers.extract_options!(args)
|
35
|
-
|
36
|
-
options[:class] = self
|
37
|
-
|
38
|
-
args.each do |klass|
|
39
|
-
store_validators_by_attribute klass.new(options, &block)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
protected ######################## PROTECTED #############################
|
44
|
-
|
45
|
-
def store_validators_by_attribute(validator)
|
46
|
-
if validator.respond_to?(:attributes) && !validator.attributes.empty?
|
47
|
-
validator.attributes.each do |attribute|
|
48
|
-
validators[attribute.to_sym] << validator
|
49
|
-
end
|
50
|
-
else
|
51
|
-
validators[nil] << validator
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
end
|
56
|
-
|
57
|
-
end
|
58
|
-
end
|