mcmire-shoulda-matchers 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.travis.yml +32 -0
- data/.yardopts +7 -0
- data/Appraisals +45 -0
- data/CONTRIBUTING.md +41 -0
- data/Gemfile +31 -0
- data/Gemfile.lock +166 -0
- data/MIT-LICENSE +22 -0
- data/NEWS.md +299 -0
- data/README.md +163 -0
- data/Rakefile +116 -0
- data/doc_config/gh-pages/index.html.erb +9 -0
- data/doc_config/yard/setup.rb +22 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/bootstrap.css +5967 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/full_list.css +12 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/global.css +45 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/solarized.css +69 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/style.css +283 -0
- data/doc_config/yard/templates/default/fulldoc/html/full_list.erb +32 -0
- data/doc_config/yard/templates/default/fulldoc/html/full_list_class.erb +1 -0
- data/doc_config/yard/templates/default/fulldoc/html/full_list_method.erb +8 -0
- data/doc_config/yard/templates/default/fulldoc/html/js/app.js +300 -0
- data/doc_config/yard/templates/default/fulldoc/html/js/full_list.js +1 -0
- data/doc_config/yard/templates/default/fulldoc/html/js/jquery.stickyheaders.js +289 -0
- data/doc_config/yard/templates/default/fulldoc/html/js/underscore.min.js +6 -0
- data/doc_config/yard/templates/default/fulldoc/html/setup.rb +8 -0
- data/doc_config/yard/templates/default/layout/html/breadcrumb.erb +14 -0
- data/doc_config/yard/templates/default/layout/html/fonts.erb +1 -0
- data/doc_config/yard/templates/default/layout/html/layout.erb +23 -0
- data/doc_config/yard/templates/default/layout/html/search.erb +13 -0
- data/doc_config/yard/templates/default/layout/html/setup.rb +8 -0
- data/doc_config/yard/templates/default/method_details/html/source.erb +10 -0
- data/doc_config/yard/templates/default/module/html/box_info.erb +31 -0
- data/features/rails_integration.feature +113 -0
- data/features/step_definitions/rails_steps.rb +162 -0
- data/features/support/env.rb +5 -0
- data/gemfiles/3.0.gemfile +24 -0
- data/gemfiles/3.0.gemfile.lock +150 -0
- data/gemfiles/3.1.gemfile +27 -0
- data/gemfiles/3.1.gemfile.lock +173 -0
- data/gemfiles/3.2.gemfile +27 -0
- data/gemfiles/3.2.gemfile.lock +171 -0
- data/gemfiles/4.0.0.gemfile +28 -0
- data/gemfiles/4.0.0.gemfile.lock +172 -0
- data/gemfiles/4.0.1.gemfile +28 -0
- data/gemfiles/4.0.1.gemfile.lock +172 -0
- data/lib/shoulda-matchers.rb +1 -0
- data/lib/shoulda/matchers.rb +11 -0
- data/lib/shoulda/matchers/action_controller.rb +17 -0
- data/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +64 -0
- data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +97 -0
- data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +81 -0
- data/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +117 -0
- data/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +114 -0
- data/lib/shoulda/matchers/action_controller/respond_with_matcher.rb +154 -0
- data/lib/shoulda/matchers/action_controller/route_matcher.rb +116 -0
- data/lib/shoulda/matchers/action_controller/route_params.rb +48 -0
- data/lib/shoulda/matchers/action_controller/set_session_matcher.rb +164 -0
- data/lib/shoulda/matchers/action_controller/set_the_flash_matcher.rb +296 -0
- data/lib/shoulda/matchers/active_model.rb +30 -0
- data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +167 -0
- data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +314 -0
- data/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +46 -0
- data/lib/shoulda/matchers/active_model/ensure_exclusion_of_matcher.rb +160 -0
- data/lib/shoulda/matchers/active_model/ensure_inclusion_of_matcher.rb +417 -0
- data/lib/shoulda/matchers/active_model/ensure_length_of_matcher.rb +337 -0
- data/lib/shoulda/matchers/active_model/errors.rb +10 -0
- data/lib/shoulda/matchers/active_model/exception_message_finder.rb +58 -0
- data/lib/shoulda/matchers/active_model/have_secure_password_matcher.rb +92 -0
- data/lib/shoulda/matchers/active_model/helpers.rb +46 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers.rb +9 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb +75 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers/even_number_matcher.rb +27 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +41 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher.rb +27 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher.rb +26 -0
- data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +112 -0
- data/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +77 -0
- data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +121 -0
- data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +380 -0
- data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +89 -0
- data/lib/shoulda/matchers/active_model/validate_uniqueness_of_matcher.rb +372 -0
- data/lib/shoulda/matchers/active_model/validation_matcher.rb +97 -0
- data/lib/shoulda/matchers/active_model/validation_message_finder.rb +69 -0
- data/lib/shoulda/matchers/active_record.rb +22 -0
- data/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +204 -0
- data/lib/shoulda/matchers/active_record/association_matcher.rb +901 -0
- data/lib/shoulda/matchers/active_record/association_matchers.rb +9 -0
- data/lib/shoulda/matchers/active_record/association_matchers/counter_cache_matcher.rb +41 -0
- data/lib/shoulda/matchers/active_record/association_matchers/dependent_matcher.rb +41 -0
- data/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +81 -0
- data/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +65 -0
- data/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +94 -0
- data/lib/shoulda/matchers/active_record/association_matchers/order_matcher.rb +41 -0
- data/lib/shoulda/matchers/active_record/association_matchers/source_matcher.rb +41 -0
- data/lib/shoulda/matchers/active_record/association_matchers/through_matcher.rb +63 -0
- data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +261 -0
- data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +149 -0
- data/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +72 -0
- data/lib/shoulda/matchers/active_record/serialize_matcher.rb +181 -0
- data/lib/shoulda/matchers/assertion_error.rb +19 -0
- data/lib/shoulda/matchers/error.rb +6 -0
- data/lib/shoulda/matchers/integrations/rspec.rb +20 -0
- data/lib/shoulda/matchers/integrations/test_unit.rb +30 -0
- data/lib/shoulda/matchers/rails_shim.rb +50 -0
- data/lib/shoulda/matchers/version.rb +6 -0
- data/lib/shoulda/matchers/warn.rb +8 -0
- data/shoulda-matchers.gemspec +23 -0
- data/spec/shoulda/matchers/action_controller/filter_param_matcher_spec.rb +22 -0
- data/spec/shoulda/matchers/action_controller/redirect_to_matcher_spec.rb +42 -0
- data/spec/shoulda/matchers/action_controller/render_template_matcher_spec.rb +78 -0
- data/spec/shoulda/matchers/action_controller/render_with_layout_matcher_spec.rb +63 -0
- data/spec/shoulda/matchers/action_controller/rescue_from_matcher_spec.rb +63 -0
- data/spec/shoulda/matchers/action_controller/respond_with_matcher_spec.rb +31 -0
- data/spec/shoulda/matchers/action_controller/route_matcher_spec.rb +70 -0
- data/spec/shoulda/matchers/action_controller/route_params_spec.rb +30 -0
- data/spec/shoulda/matchers/action_controller/set_session_matcher_spec.rb +51 -0
- data/spec/shoulda/matchers/action_controller/set_the_flash_matcher_spec.rb +153 -0
- data/spec/shoulda/matchers/active_model/allow_mass_assignment_of_matcher_spec.rb +111 -0
- data/spec/shoulda/matchers/active_model/allow_value_matcher_spec.rb +170 -0
- data/spec/shoulda/matchers/active_model/disallow_value_matcher_spec.rb +81 -0
- data/spec/shoulda/matchers/active_model/ensure_exclusion_of_matcher_spec.rb +95 -0
- data/spec/shoulda/matchers/active_model/ensure_inclusion_of_matcher_spec.rb +320 -0
- data/spec/shoulda/matchers/active_model/ensure_length_of_matcher_spec.rb +166 -0
- data/spec/shoulda/matchers/active_model/exception_message_finder_spec.rb +111 -0
- data/spec/shoulda/matchers/active_model/have_secure_password_matcher_spec.rb +20 -0
- data/spec/shoulda/matchers/active_model/helpers_spec.rb +158 -0
- data/spec/shoulda/matchers/active_model/numericality_matchers/comparison_matcher_spec.rb +169 -0
- data/spec/shoulda/matchers/active_model/numericality_matchers/even_number_matcher_spec.rb +59 -0
- data/spec/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher_spec.rb +59 -0
- data/spec/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher_spec.rb +57 -0
- data/spec/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb +139 -0
- data/spec/shoulda/matchers/active_model/validate_acceptance_of_matcher_spec.rb +41 -0
- data/spec/shoulda/matchers/active_model/validate_confirmation_of_matcher_spec.rb +47 -0
- data/spec/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +331 -0
- data/spec/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +180 -0
- data/spec/shoulda/matchers/active_model/validate_uniqueness_of_matcher_spec.rb +398 -0
- data/spec/shoulda/matchers/active_model/validation_message_finder_spec.rb +127 -0
- data/spec/shoulda/matchers/active_record/accept_nested_attributes_for_matcher_spec.rb +107 -0
- data/spec/shoulda/matchers/active_record/association_matcher_spec.rb +860 -0
- data/spec/shoulda/matchers/active_record/association_matchers/model_reflection_spec.rb +247 -0
- data/spec/shoulda/matchers/active_record/have_db_column_matcher_spec.rb +111 -0
- data/spec/shoulda/matchers/active_record/have_db_index_matcher_spec.rb +78 -0
- data/spec/shoulda/matchers/active_record/have_readonly_attributes_matcher_spec.rb +41 -0
- data/spec/shoulda/matchers/active_record/serialize_matcher_spec.rb +86 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/active_model_versions.rb +13 -0
- data/spec/support/active_resource_builder.rb +29 -0
- data/spec/support/activemodel_helpers.rb +19 -0
- data/spec/support/capture_helpers.rb +19 -0
- data/spec/support/class_builder.rb +42 -0
- data/spec/support/controller_builder.rb +74 -0
- data/spec/support/fail_with_message_including_matcher.rb +33 -0
- data/spec/support/fail_with_message_matcher.rb +32 -0
- data/spec/support/i18n_faker.rb +10 -0
- data/spec/support/mailer_builder.rb +10 -0
- data/spec/support/model_builder.rb +81 -0
- data/spec/support/rails_versions.rb +18 -0
- data/spec/support/shared_examples/numerical_submatcher.rb +19 -0
- data/spec/support/shared_examples/numerical_type_submatcher.rb +17 -0
- data/spec/support/test_application.rb +120 -0
- data/yard.watchr +5 -0
- metadata +281 -0
@@ -0,0 +1,41 @@
|
|
1
|
+
module Shoulda
|
2
|
+
module Matchers
|
3
|
+
module ActiveRecord
|
4
|
+
module AssociationMatchers
|
5
|
+
# @private
|
6
|
+
class CounterCacheMatcher
|
7
|
+
attr_accessor :missing_option
|
8
|
+
|
9
|
+
def initialize(counter_cache, name)
|
10
|
+
@counter_cache = counter_cache
|
11
|
+
@name = name
|
12
|
+
@missing_option = ''
|
13
|
+
end
|
14
|
+
|
15
|
+
def description
|
16
|
+
"counter_cache => #{counter_cache}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def matches?(subject)
|
20
|
+
self.subject = ModelReflector.new(subject, name)
|
21
|
+
|
22
|
+
if option_verifier.correct_for_string?(:counter_cache, counter_cache)
|
23
|
+
true
|
24
|
+
else
|
25
|
+
self.missing_option = "#{name} should have #{description}"
|
26
|
+
false
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
attr_accessor :subject, :counter_cache, :name
|
33
|
+
|
34
|
+
def option_verifier
|
35
|
+
@option_verifier ||= OptionVerifier.new(subject)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Shoulda
|
2
|
+
module Matchers
|
3
|
+
module ActiveRecord
|
4
|
+
module AssociationMatchers
|
5
|
+
# @private
|
6
|
+
class DependentMatcher
|
7
|
+
attr_accessor :missing_option
|
8
|
+
|
9
|
+
def initialize(dependent, name)
|
10
|
+
@dependent = dependent
|
11
|
+
@name = name
|
12
|
+
@missing_option = ''
|
13
|
+
end
|
14
|
+
|
15
|
+
def description
|
16
|
+
"dependent => #{dependent}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def matches?(subject)
|
20
|
+
self.subject = ModelReflector.new(subject, name)
|
21
|
+
|
22
|
+
if option_verifier.correct_for_string?(:dependent, dependent)
|
23
|
+
true
|
24
|
+
else
|
25
|
+
self.missing_option = "#{name} should have #{dependent} dependency"
|
26
|
+
false
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
attr_accessor :subject, :dependent, :name
|
33
|
+
|
34
|
+
def option_verifier
|
35
|
+
@option_verifier ||= OptionVerifier.new(subject)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
module Shoulda
|
4
|
+
module Matchers
|
5
|
+
module ActiveRecord
|
6
|
+
module AssociationMatchers
|
7
|
+
# @private
|
8
|
+
class ModelReflection < SimpleDelegator
|
9
|
+
def initialize(reflection)
|
10
|
+
super(reflection)
|
11
|
+
@reflection = reflection
|
12
|
+
@subject = reflection.active_record
|
13
|
+
end
|
14
|
+
|
15
|
+
def associated_class
|
16
|
+
reflection.klass
|
17
|
+
end
|
18
|
+
|
19
|
+
def through?
|
20
|
+
reflection.options[:through]
|
21
|
+
end
|
22
|
+
|
23
|
+
def join_table
|
24
|
+
join_table =
|
25
|
+
if reflection.respond_to?(:join_table)
|
26
|
+
reflection.join_table
|
27
|
+
else
|
28
|
+
reflection.options[:join_table]
|
29
|
+
end
|
30
|
+
|
31
|
+
join_table.to_s
|
32
|
+
end
|
33
|
+
|
34
|
+
def association_relation
|
35
|
+
if reflection.respond_to?(:scope)
|
36
|
+
convert_scope_to_relation(reflection.scope)
|
37
|
+
else
|
38
|
+
convert_options_to_relation(reflection.options)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
attr_reader :reflection, :subject
|
45
|
+
|
46
|
+
def convert_scope_to_relation(scope)
|
47
|
+
relation = associated_class.all
|
48
|
+
|
49
|
+
if scope
|
50
|
+
# Source: AR::Associations::AssociationScope#eval_scope
|
51
|
+
relation.instance_exec(subject, &scope)
|
52
|
+
else
|
53
|
+
relation
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def convert_options_to_relation(options)
|
58
|
+
relation = associated_class.scoped
|
59
|
+
relation = extend_relation_with(relation, :where, options[:conditions])
|
60
|
+
relation = extend_relation_with(relation, :includes, options[:include])
|
61
|
+
relation = extend_relation_with(relation, :order, options[:order])
|
62
|
+
relation = extend_relation_with(relation, :group, options[:group])
|
63
|
+
relation = extend_relation_with(relation, :having, options[:having])
|
64
|
+
relation = extend_relation_with(relation, :limit, options[:limit])
|
65
|
+
relation = extend_relation_with(relation, :offset, options[:offset])
|
66
|
+
relation = extend_relation_with(relation, :select, options[:select])
|
67
|
+
relation
|
68
|
+
end
|
69
|
+
|
70
|
+
def extend_relation_with(relation, method_name, value)
|
71
|
+
if value
|
72
|
+
relation.__send__(method_name, value)
|
73
|
+
else
|
74
|
+
relation
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Shoulda
|
2
|
+
module Matchers
|
3
|
+
module ActiveRecord
|
4
|
+
module AssociationMatchers
|
5
|
+
# @private
|
6
|
+
class ModelReflector
|
7
|
+
delegate :associated_class, :through?, :join_table,
|
8
|
+
:association_relation, to: :reflection
|
9
|
+
|
10
|
+
def initialize(subject, name)
|
11
|
+
@subject = subject
|
12
|
+
@name = name
|
13
|
+
end
|
14
|
+
|
15
|
+
def reflection
|
16
|
+
@reflection ||= reflect_on_association(name)
|
17
|
+
end
|
18
|
+
|
19
|
+
def reflect_on_association(name)
|
20
|
+
reflection = model_class.reflect_on_association(name)
|
21
|
+
|
22
|
+
if reflection
|
23
|
+
ModelReflection.new(reflection)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def model_class
|
28
|
+
subject.class
|
29
|
+
end
|
30
|
+
|
31
|
+
def build_relation_with_clause(name, value)
|
32
|
+
case name
|
33
|
+
when :conditions then associated_class.where(value)
|
34
|
+
when :order then associated_class.order(value)
|
35
|
+
else raise ArgumentError, "Unknown clause '#{name}'"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def extract_relation_clause_from(relation, name)
|
40
|
+
case name
|
41
|
+
when :conditions
|
42
|
+
relation.where_values_hash
|
43
|
+
when :order
|
44
|
+
relation.order_values.map { |value| value_as_sql(value) }.join(', ')
|
45
|
+
else
|
46
|
+
raise ArgumentError, "Unknown clause '#{name}'"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
attr_reader :subject, :name
|
53
|
+
|
54
|
+
def value_as_sql(value)
|
55
|
+
if value.respond_to?(:to_sql)
|
56
|
+
value.to_sql
|
57
|
+
else
|
58
|
+
value
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Shoulda
|
2
|
+
module Matchers
|
3
|
+
module ActiveRecord
|
4
|
+
module AssociationMatchers
|
5
|
+
# @private
|
6
|
+
class OptionVerifier
|
7
|
+
delegate :reflection, to: :reflector
|
8
|
+
|
9
|
+
attr_reader :reflector
|
10
|
+
|
11
|
+
RELATION_OPTIONS = [:conditions, :order]
|
12
|
+
|
13
|
+
def initialize(reflector)
|
14
|
+
@reflector = reflector
|
15
|
+
end
|
16
|
+
|
17
|
+
def correct_for_string?(name, expected_value)
|
18
|
+
correct_for?(:string, name, expected_value)
|
19
|
+
end
|
20
|
+
|
21
|
+
def correct_for_boolean?(name, expected_value)
|
22
|
+
correct_for?(:boolean, name, expected_value)
|
23
|
+
end
|
24
|
+
|
25
|
+
def correct_for_hash?(name, expected_value)
|
26
|
+
correct_for?(:hash, name, expected_value)
|
27
|
+
end
|
28
|
+
|
29
|
+
def correct_for_relation_clause?(name, expected_value)
|
30
|
+
correct_for?(:relation_clause, name, expected_value)
|
31
|
+
end
|
32
|
+
|
33
|
+
def actual_value_for(name)
|
34
|
+
if RELATION_OPTIONS.include?(name)
|
35
|
+
actual_value_for_relation_clause(name)
|
36
|
+
else
|
37
|
+
method_name = "actual_value_for_#{name}"
|
38
|
+
if respond_to?(method_name, true)
|
39
|
+
__send__(method_name)
|
40
|
+
else
|
41
|
+
reflection.options[name]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
attr_reader :reflector
|
49
|
+
|
50
|
+
def correct_for?(*args)
|
51
|
+
expected_value, name, type = args.reverse
|
52
|
+
if expected_value.nil?
|
53
|
+
true
|
54
|
+
else
|
55
|
+
expected_value = type_cast(type, expected_value_for(name, expected_value))
|
56
|
+
actual_value = type_cast(type, actual_value_for(name))
|
57
|
+
expected_value == actual_value
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def type_cast(type, value)
|
62
|
+
case type
|
63
|
+
when :string, :relation_clause then value.to_s
|
64
|
+
when :boolean then !!value
|
65
|
+
when :hash then Hash(value).stringify_keys
|
66
|
+
else value
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def expected_value_for(name, value)
|
71
|
+
if RELATION_OPTIONS.include?(name)
|
72
|
+
expected_value_for_relation_clause(name, value)
|
73
|
+
else
|
74
|
+
value
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def expected_value_for_relation_clause(name, value)
|
79
|
+
relation = reflector.build_relation_with_clause(name, value)
|
80
|
+
reflector.extract_relation_clause_from(relation, name)
|
81
|
+
end
|
82
|
+
|
83
|
+
def actual_value_for_relation_clause(name)
|
84
|
+
reflector.extract_relation_clause_from(reflector.association_relation, name)
|
85
|
+
end
|
86
|
+
|
87
|
+
def actual_value_for_class_name
|
88
|
+
reflector.associated_class
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Shoulda
|
2
|
+
module Matchers
|
3
|
+
module ActiveRecord
|
4
|
+
module AssociationMatchers
|
5
|
+
# @private
|
6
|
+
class OrderMatcher
|
7
|
+
attr_accessor :missing_option
|
8
|
+
|
9
|
+
def initialize(order, name)
|
10
|
+
@order = order
|
11
|
+
@name = name
|
12
|
+
@missing_option = ''
|
13
|
+
end
|
14
|
+
|
15
|
+
def description
|
16
|
+
"order => #{order}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def matches?(subject)
|
20
|
+
self.subject = ModelReflector.new(subject, name)
|
21
|
+
|
22
|
+
if option_verifier.correct_for_relation_clause?(:order, order)
|
23
|
+
true
|
24
|
+
else
|
25
|
+
self.missing_option = "#{name} should be ordered by #{order}"
|
26
|
+
false
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
attr_accessor :subject, :order, :name
|
33
|
+
|
34
|
+
def option_verifier
|
35
|
+
@option_verifier ||= OptionVerifier.new(subject)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Shoulda
|
2
|
+
module Matchers
|
3
|
+
module ActiveRecord
|
4
|
+
module AssociationMatchers
|
5
|
+
# @private
|
6
|
+
class SourceMatcher
|
7
|
+
attr_accessor :missing_option
|
8
|
+
|
9
|
+
def initialize(source, name)
|
10
|
+
@source = source
|
11
|
+
@name = name
|
12
|
+
@missing_option = ''
|
13
|
+
end
|
14
|
+
|
15
|
+
def description
|
16
|
+
"source => #{source}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def matches?(subject)
|
20
|
+
self.subject = ModelReflector.new(subject, name)
|
21
|
+
|
22
|
+
if option_verifier.correct_for_string?(:source, source)
|
23
|
+
true
|
24
|
+
else
|
25
|
+
self.missing_option = "#{name} should have #{source} as source option"
|
26
|
+
false
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
attr_accessor :subject, :source, :name
|
33
|
+
|
34
|
+
def option_verifier
|
35
|
+
@option_verifier ||= OptionVerifier.new(subject)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Shoulda
|
2
|
+
module Matchers
|
3
|
+
module ActiveRecord
|
4
|
+
module AssociationMatchers
|
5
|
+
# @private
|
6
|
+
class ThroughMatcher
|
7
|
+
attr_accessor :missing_option
|
8
|
+
|
9
|
+
def initialize(through, name)
|
10
|
+
@through = through
|
11
|
+
@name = name
|
12
|
+
@missing_option = ''
|
13
|
+
end
|
14
|
+
|
15
|
+
def description
|
16
|
+
"through #{through}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def matches?(subject)
|
20
|
+
self.subject = ModelReflector.new(subject, name)
|
21
|
+
through.nil? || association_set_properly?
|
22
|
+
end
|
23
|
+
|
24
|
+
def association_set_properly?
|
25
|
+
through_association_exists? && through_association_correct?
|
26
|
+
end
|
27
|
+
|
28
|
+
def through_association_exists?
|
29
|
+
if through_reflection.present?
|
30
|
+
true
|
31
|
+
else
|
32
|
+
self.missing_option = "#{name} does not have any relationship to #{through}"
|
33
|
+
false
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def through_reflection
|
38
|
+
@through_reflection ||= subject.reflect_on_association(through)
|
39
|
+
end
|
40
|
+
|
41
|
+
def through_association_correct?
|
42
|
+
if option_verifier.correct_for_string?(:through, through)
|
43
|
+
true
|
44
|
+
else
|
45
|
+
self.missing_option =
|
46
|
+
"Expected #{name} to have #{name} through #{through}, " +
|
47
|
+
"but got it through #{option_verifier.actual_value_for(:through)}"
|
48
|
+
false
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
attr_accessor :through, :name, :subject
|
55
|
+
|
56
|
+
def option_verifier
|
57
|
+
@option_verifier ||= OptionVerifier.new(subject)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|