rest_my_case 1.7.0 → 1.7.4
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/.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
|