shoulda_matchmakers 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +21 -0
  4. data/lib/controller/action_controller/action_controller_controller_sm_model.rb +53 -0
  5. data/lib/controller/action_controller/action_controller_controller_sm_model_helper.rb +73 -0
  6. data/lib/controller/action_controller/matchmakers/callbacks.rb +56 -0
  7. data/lib/controller/action_controller/matchmakers/filter_param.rb +69 -0
  8. data/lib/controller/action_controller/matchmakers/permit.rb +510 -0
  9. data/lib/controller/action_controller/matchmakers/redirect_to.rb +126 -0
  10. data/lib/controller/action_controller/matchmakers/render_template.rb +198 -0
  11. data/lib/controller/action_controller/matchmakers/render_with_layout.rb +72 -0
  12. data/lib/controller/action_controller/matchmakers/rescue_from.rb +96 -0
  13. data/lib/controller/action_controller/matchmakers/respond_with.rb +71 -0
  14. data/lib/controller/action_controller/matchmakers/route.rb +586 -0
  15. data/lib/controller/action_controller/matchmakers/set_flash.rb +136 -0
  16. data/lib/controller/action_controller/matchmakers/set_session.rb +115 -0
  17. data/lib/controller/action_controller/permitted_params_definition.rb +60 -0
  18. data/lib/generators/shoulda_matchmakers/controller_matcher_generator.rb +87 -0
  19. data/lib/generators/shoulda_matchmakers/controller_matcher_generator_helper.rb +92 -0
  20. data/lib/generators/shoulda_matchmakers/factory_generator.rb +86 -0
  21. data/lib/generators/shoulda_matchmakers/install_generator.rb +10 -0
  22. data/lib/generators/shoulda_matchmakers/model_matcher_generator.rb +87 -0
  23. data/lib/generators/shoulda_matchmakers/model_matcher_generator_helper.rb +107 -0
  24. data/lib/model/active_record/active_record_model_sm_model.rb +50 -0
  25. data/lib/model/active_record/active_record_model_sm_model_helper.rb +206 -0
  26. data/lib/model/active_record/factory_sm_model.rb +28 -0
  27. data/lib/model/active_record/factory_sm_model_helper.rb +124 -0
  28. data/lib/model/active_record/matchmakers/accept_nested_attributes_for.rb +66 -0
  29. data/lib/model/active_record/matchmakers/allow_value.rb +137 -0
  30. data/lib/model/active_record/matchmakers/associations.rb +52 -0
  31. data/lib/model/active_record/matchmakers/define_enum_for.rb +53 -0
  32. data/lib/model/active_record/matchmakers/delegate_method.rb +101 -0
  33. data/lib/model/active_record/matchmakers/have_db_column.rb +33 -0
  34. data/lib/model/active_record/matchmakers/have_db_index.rb +39 -0
  35. data/lib/model/active_record/matchmakers/have_readonly_attribute.rb +32 -0
  36. data/lib/model/active_record/matchmakers/have_secure_password.rb +32 -0
  37. data/lib/model/active_record/matchmakers/serialize.rb +67 -0
  38. data/lib/model/active_record/matchmakers/validations.rb +169 -0
  39. data/lib/model/active_record/options_definition.rb +160 -0
  40. data/lib/shoulda_matchmakers.rb +48 -0
  41. data/lib/shoulda_matchmakers/version.rb +3 -0
  42. data/lib/support/command_line_interface.rb +100 -0
  43. data/lib/support/controller_generator.rb +198 -0
  44. data/lib/support/indefinite_article.rb +70 -0
  45. data/lib/support/to_discard/belong_to.rb +94 -0
  46. data/lib/support/to_discard/have_and_belong_to_many.rb +83 -0
  47. data/lib/support/to_discard/have_many.rb +96 -0
  48. data/lib/support/to_discard/have_one.rb +98 -0
  49. data/lib/support/to_discard/permit_refactor.rb +270 -0
  50. data/lib/support/to_discard/render_template_new.rb +204 -0
  51. data/lib/support/to_discard/render_template_reconstruction.rb +188 -0
  52. data/lib/support/to_discard/use_around_action.rb +20 -0
  53. data/lib/support/to_discard/use_before_action.rb +20 -0
  54. data/lib/support/to_discard/validate_absence_of.rb +16 -0
  55. data/lib/support/to_discard/validate_acceptance_of.rb +16 -0
  56. data/lib/support/to_discard/validate_confirmation_of.rb +16 -0
  57. data/lib/support/to_discard/validate_exclusion_of.rb +145 -0
  58. data/lib/support/to_discard/validate_inclusion_of.rb +94 -0
  59. data/lib/support/to_discard/validate_length_of.rb +16 -0
  60. data/lib/support/to_discard/validate_numericality_of.rb +16 -0
  61. data/lib/support/to_discard/validate_presence_of.rb +16 -0
  62. data/lib/support/to_discard/validate_uniqueness_of.rb +16 -0
  63. data/lib/support/to_discard/validation_old.rb +37 -0
  64. data/lib/support/to_discard/validations.rb +41 -0
  65. data/lib/support/to_discard/validations_conditional.rb +146 -0
  66. data/lib/support/trace_debug_lines.txt +319 -0
  67. data/lib/support/util.rb +15 -0
  68. data/lib/templates/controller/action_controller/controller_spec_template.haml +146 -0
  69. data/lib/templates/factory/active_record/factory_template.haml +13 -0
  70. data/lib/templates/model/active_record/model_spec_template.haml +233 -0
  71. data/lib/templates/shoulda_matchmakers.rb +112 -0
  72. metadata +263 -0
@@ -0,0 +1,86 @@
1
+ require 'haml'
2
+ require_relative 'model_matcher_generator_helper'
3
+ require 'model/active_record/factory_sm_model'
4
+ require 'spin_to_win'
5
+
6
+ module ShouldaMatchmakers
7
+ class FactoryGenerator < ::Rails::Generators::Base
8
+
9
+ include Generator::ActiveRecord::ModelMatcherGeneratorHelper
10
+
11
+ source_root(File.expand_path(File.dirname(__FILE__)))
12
+
13
+ class_option :include, type: :array,
14
+ require: false,
15
+ aliases: '-i',
16
+ default: [],
17
+ desc: "Sets list of application ActiveRecord class names of models to INCLUDE in generated factories.\n" +
18
+ " By default, factories are generated for all ActiveRecord::Base descendant class models.\n" +
19
+ " When used, '_included' and '_excluded' settings in '~/config/initializers/shoulda_matchmakers.rb'\n" +
20
+ " configuration file are ignored. Example (space delimited, include namespaces):\n\n" +
21
+ " -i Driver License Vehicle::Car Vehicle::Bus\n\n\n"
22
+
23
+ class_option :exclude, type: :array,
24
+ require: false,
25
+ aliases: '-e',
26
+ default: [],
27
+ desc: "Sets list of application ActiveRecord class names of models to EXCLUDE from generated factories.\n" +
28
+ " By default, no ActiveRecord::Base descendant class models are excluded from generated factories.\n" +
29
+ " When used, '_included' and '_excluded' settings in '~/config/initializers/shoulda_matchmakers.rb'\n" +
30
+ " configuration file are ignored. Example (space delimited, include namespaces):\n\n" +
31
+ " -e Driver Vehicle::Car\n\n\n"
32
+
33
+ class_option :include_and_config, type: :array,
34
+ require: false,
35
+ aliases: '-I',
36
+ default: [],
37
+ desc: "Same as '-i/-include', except that '_included' and '_excluded' settings in\n" +
38
+ " '~/config/initializers/shoulda_matchmakers.rb' are not ignored. Configuration file\n" +
39
+ " settings are applied first then the class names listed with this option are applied.\n" +
40
+ " Example (space delimited, include namespaces):\n\n" +
41
+ " -I Driver License Vehicle::Car Vehicle::Bus\n\n\n"
42
+
43
+ class_option :exclude_and_config, type: :array,
44
+ require: false,
45
+ aliases: '-E',
46
+ default: [],
47
+ desc: "Same as '-e/-exclude', except that '_included' and '_excluded' settings in\n" +
48
+ " '~/config/initializers/shoulda_matchmakers.rb' are not ignored. Configuration file\n" +
49
+ " settings are applied first then the class names listed with this option are applied.\n" +
50
+ " Example (space delimited, include namespaces):\n\n" +
51
+ " -E Driver Vehicle::Car\n\n\n"
52
+
53
+ def create_model_factories
54
+ puts "\n"
55
+ generator = "factory"
56
+ generator_options = options.to_hash
57
+ working_generated_code_line_length = ::ShouldaMatchmakers.configuration.preferred_generated_code_line_length - 6
58
+ SpinToWin.with_spinner('ShouldaMatchmakers:Factories') do |spinner|
59
+ spinner.banner('initializing...')
60
+ load_application
61
+ @app_active_record_descendants_names = get_app_active_record_descendants_names
62
+ end
63
+ puts "\n"
64
+ generate_active_record_model_factories(generator, generator_options, @app_active_record_descendants_names, working_generated_code_line_length)
65
+ end
66
+
67
+
68
+ private
69
+
70
+ def generate_active_record_model_factories(generator, generator_options, app_active_record_descendants_names, code_line_length)
71
+ if app_active_record_descendants_names.present?
72
+ selected_app_active_record_descendants_names = filter_app_active_record_descendants_names(generator, generator_options, app_active_record_descendants_names)
73
+ selected_app_active_record_descendants_names.each do |app_class_name|
74
+ save_generate(app_class_name, generator) do
75
+ @active_record_model_factory_sm_model = ::ShouldaMatchmakers::Model::ActiveRecord::FactorySmModel.new(app_class_name, code_line_length)
76
+ template_filename = File.expand_path('../../templates/factory/active_record/factory_template.haml', File.dirname(__FILE__))
77
+ template = File.read(template_filename)
78
+ create_file "#{ ::ShouldaMatchmakers.configuration.active_record_model_factories_path }/#{ app_class_name.underscore }_factory.rb",
79
+ Haml::Engine.new(template, filename: template_filename, format: :html5).to_html(binding)
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+ end
86
+ end
@@ -0,0 +1,10 @@
1
+ module ShouldaMatchmakers
2
+ class InstallGenerator < Rails::Generators::Base
3
+ source_root(File.expand_path(File.dirname(__FILE__)))
4
+
5
+ def copy_initializer
6
+ copy_file '../../templates/shoulda_matchmakers.rb', 'config/initializers/shoulda_matchmakers.rb'
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,87 @@
1
+ require 'haml'
2
+ require_relative 'model_matcher_generator_helper'
3
+ require 'model/active_record/active_record_model_sm_model'
4
+ require 'spin_to_win'
5
+
6
+ module ShouldaMatchmakers
7
+ class ModelMatcherGenerator < ::Rails::Generators::Base
8
+
9
+ include Generator::ActiveRecord::ModelMatcherGeneratorHelper
10
+
11
+ source_root(File.expand_path(File.dirname(__FILE__)))
12
+
13
+ class_option :include, type: :array,
14
+ require: false,
15
+ aliases: '-i',
16
+ default: [],
17
+ desc: "Sets list of application ActiveRecord models to INCLUDE in generated tests.\n" +
18
+ " By default, tests are generated for all ActiveRecord::Base descendant classes.\n" +
19
+ " When used, '_included' and '_excluded' settings in '~/config/initializers/shoulda_matchmakers.rb'\n" +
20
+ " configuration file are ignored. Example (space delimited, include namespaces):\n\n" +
21
+ " -i Driver License Vehicle::Car Vehicle::Bus\n\n\n"
22
+
23
+ class_option :exclude, type: :array,
24
+ require: false,
25
+ aliases: '-e',
26
+ default: [],
27
+ desc: "Sets list of application ActiveRecord models to EXCLUDE from generated tests.\n" +
28
+ " By default, no ActiveRecord::Base descendant classes are excluded from generated tests.\n" +
29
+ " When used, '_included' and '_excluded' settings in '~/config/initializers/shoulda_matchmakers.rb'\n" +
30
+ " configuration file are ignored. Example (space delimited, include namespaces):\n\n" +
31
+ " -e Driver Vehicle::Car\n\n\n"
32
+
33
+ class_option :include_and_config, type: :array,
34
+ require: false,
35
+ aliases: '-I',
36
+ default: [],
37
+ desc: "Same as '-i/-include', except that '_included' and '_excluded' settings in\n" +
38
+ " '~/config/initializers/shoulda_matchmakers.rb' are not ignored. Configuration file\n" +
39
+ " settings are applied first then the class names listed with this option are applied.\n" +
40
+ " Example (space delimited, include namespaces):\n\n" +
41
+ " -I Driver License Vehicle::Car Vehicle::Bus\n\n\n"
42
+
43
+ class_option :exclude_and_config, type: :array,
44
+ require: false,
45
+ aliases: '-E',
46
+ default: [],
47
+ desc: "Same as '-e/-exclude', except that '_included' and '_excluded' settings in\n" +
48
+ " '~/config/initializers/shoulda_matchmakers.rb' are not ignored. Configuration file\n" +
49
+ " settings are applied first then the class names listed with this option are applied.\n" +
50
+ " Example (space delimited, include namespaces):\n\n" +
51
+ " -E Driver Vehicle::Car\n\n\n"
52
+
53
+ def create_model_matchmakers
54
+ puts "\n"
55
+ generator = "model"
56
+ generator_options = options.to_hash
57
+ working_generated_code_line_length = ::ShouldaMatchmakers.configuration.preferred_generated_code_line_length - 6
58
+ SpinToWin.with_spinner('ShouldaMatchmakers:ModelMatchers') do |spinner|
59
+ spinner.banner('initializing...')
60
+ load_application
61
+ @app_active_record_descendants_names = get_app_active_record_descendants_names
62
+ end
63
+ puts "\n"
64
+ generate_active_record_model_matchmakers(generator, generator_options, @app_active_record_descendants_names, working_generated_code_line_length)
65
+ end
66
+
67
+
68
+ private
69
+
70
+ def generate_active_record_model_matchmakers(generator, generator_options, app_active_record_descendants_names, code_line_length)
71
+ if app_active_record_descendants_names.present?
72
+ selected_app_active_record_descendants_names = filter_app_active_record_descendants_names(generator, generator_options, app_active_record_descendants_names)
73
+ selected_app_active_record_descendants_names.each do |app_class_name|
74
+ save_generate(app_class_name, generator) do
75
+ @active_record_model_sm_model = ::ShouldaMatchmakers::Model::ActiveRecord::ActiveRecordModelSmModel.new(app_class_name, app_active_record_descendants_names, code_line_length)
76
+ template_filename = File.expand_path('../../templates/model/active_record/model_spec_template.haml', File.dirname(__FILE__))
77
+ template = File.read(template_filename)
78
+ create_file "#{ ::ShouldaMatchmakers.configuration.active_record_model_tests_path }/#{ app_class_name.underscore }_spec.rb",
79
+ Haml::Engine.new(template, filename: template_filename, format: :html5).to_html(binding)
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+ end
86
+ end
87
+
@@ -0,0 +1,107 @@
1
+ module ShouldaMatchmakers
2
+ module Generator
3
+ module ActiveRecord
4
+ module ModelMatcherGeneratorHelper
5
+
6
+ def load_application
7
+ Rails.application.try(:eager_load!)
8
+ end
9
+
10
+ def get_app_active_record_descendants_names
11
+ if defined?(::ActiveRecord::Base)
12
+ ::ActiveRecord::Base.descendants.map(&:name)
13
+ else
14
+ []
15
+ end
16
+ end
17
+
18
+ def save_generate(class_name, generator)
19
+ begin
20
+ yield
21
+ rescue => e
22
+ if generator == "model"
23
+ puts "Cannot create model spec for #{ class_name }. Reason #{ e.message }"
24
+ else
25
+ puts "Cannot create factory for #{ class_name }. Reason #{ e.message }"
26
+ end
27
+ end
28
+ end
29
+
30
+ def filter_app_active_record_descendants_names(generator, generator_options, app_active_record_class_names)
31
+
32
+ generator_include_option_active_record_class_names = generator_options.fetch('include')
33
+ generator_exclude_option_active_record_class_names = generator_options.fetch('exclude')
34
+ generator_include_and_config_options_active_record_class_names = generator_options.fetch('include_and_config')
35
+ generator_exclude_and_config_options_active_record_class_names = generator_options.fetch('exclude_and_config')
36
+
37
+ if generator_include_option_active_record_class_names.present?
38
+ filter_active_record_class_names_with_include_option(app_active_record_class_names, generator_include_option_active_record_class_names)
39
+
40
+ elsif generator_exclude_option_active_record_class_names.present?
41
+ filter_active_record_class_names_with_exclude_option(app_active_record_class_names, generator_exclude_option_active_record_class_names)
42
+
43
+ elsif generator_include_and_config_options_active_record_class_names.present?
44
+ filter_active_record_class_names_with_generator_include_and_config_options(app_active_record_class_names, generator_include_and_config_options_active_record_class_names, generator)
45
+
46
+ elsif generator_exclude_and_config_options_active_record_class_names.present?
47
+ filter_active_record_class_names_with_generator_exclude_and_config_options(app_active_record_class_names, generator_exclude_and_config_options_active_record_class_names, generator)
48
+
49
+ else
50
+ selected_app_active_record_class_names = filter_active_record_class_names_with_config_options(app_active_record_class_names, generator)
51
+ if selected_app_active_record_class_names.present?
52
+ selected_app_active_record_class_names
53
+ else
54
+ app_active_record_class_names.uniq.sort
55
+ end
56
+ end
57
+
58
+ end
59
+
60
+ def filter_active_record_class_names_with_include_option(app_active_record_class_names, include_option_active_record_class_names)
61
+ app_active_record_class_names.map.select { |app_class_name| include_option_active_record_class_names.include? app_class_name }.uniq.sort
62
+ end
63
+
64
+ def filter_active_record_class_names_with_exclude_option(app_active_record_class_names, exclude_option_active_record_class_names)
65
+ app_active_record_class_names.map.reject { |app_class_name| exclude_option_active_record_class_names.include? app_class_name }.uniq.sort
66
+ end
67
+
68
+ def filter_active_record_class_names_with_generator_include_and_config_options(app_active_record_class_names, generator_include_and_config_options_active_record_class_names, generator)
69
+ selected_app_active_record_class_names = filter_active_record_class_names_with_config_options(app_active_record_class_names, generator)
70
+ if selected_app_active_record_class_names.present?
71
+ selected_app_active_record_class_names +
72
+ filter_active_record_class_names_with_include_option(app_active_record_class_names, generator_include_and_config_options_active_record_class_names).uniq.sort
73
+ else
74
+ filter_active_record_class_names_with_include_option(app_active_record_class_names, generator_include_and_config_options_active_record_class_names).uniq.sort
75
+ end
76
+ end
77
+
78
+ def filter_active_record_class_names_with_generator_exclude_and_config_options(app_active_record_class_names, generator_exclude_and_config_options_active_record_class_names, generator)
79
+ selected_active_record_model_names = filter_active_record_class_names_with_config_options(app_active_record_class_names, generator)
80
+ if selected_active_record_model_names.present?
81
+ filter_active_record_class_names_with_exclude_option(selected_active_record_model_names, generator_exclude_and_config_options_active_record_class_names).uniq.sort
82
+ else
83
+ filter_active_record_class_names_with_exclude_option(app_active_record_class_names, generator_exclude_and_config_options_active_record_class_names).uniq.sort
84
+ end
85
+ end
86
+
87
+ def filter_active_record_class_names_with_config_options(app_active_record_class_names, generator)
88
+ if generator == "model"
89
+ config_included_option_active_record_class_names = ::ShouldaMatchmakers.configuration.active_record_class_names_included
90
+ config_excluded_option_active_record_class_names = ::ShouldaMatchmakers.configuration.active_record_class_names_excluded
91
+ else
92
+ config_included_option_active_record_class_names = ::ShouldaMatchmakers.configuration.active_record_model_class_names_for_factories_included
93
+ config_excluded_option_active_record_class_names = ::ShouldaMatchmakers.configuration.active_record_model_class_names_for_factories_excluded
94
+ end
95
+ if config_included_option_active_record_class_names.present?
96
+ filter_active_record_class_names_with_include_option(app_active_record_class_names, config_included_option_active_record_class_names).uniq.sort
97
+ elsif config_excluded_option_active_record_class_names.present?
98
+ filter_active_record_class_names_with_exclude_option(app_active_record_class_names, config_excluded_option_active_record_class_names).uniq.sort
99
+ else
100
+ []
101
+ end
102
+ end
103
+
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,50 @@
1
+ require_relative 'matchmakers/accept_nested_attributes_for'
2
+ require_relative 'matchmakers/allow_value'
3
+ require_relative 'matchmakers/associations'
4
+ require_relative 'matchmakers/define_enum_for'
5
+ require_relative 'matchmakers/delegate_method'
6
+ require_relative 'matchmakers/have_db_column'
7
+ require_relative 'matchmakers/have_db_index'
8
+ require_relative 'matchmakers/have_readonly_attribute'
9
+ require_relative 'matchmakers/have_secure_password'
10
+ require_relative 'matchmakers/serialize'
11
+ require_relative 'matchmakers/validations'
12
+ require_relative 'active_record_model_sm_model_helper'
13
+
14
+
15
+ module ShouldaMatchmakers
16
+ module Model
17
+ module ActiveRecord
18
+ class ActiveRecordModelSmModel
19
+
20
+ ### Includes ###
21
+ include Matchmaker::AllowValue
22
+ include Matchmaker::Associations
23
+ include Matchmaker::AcceptNestedAttributesFor
24
+ include Matchmaker::DefineEnumFor
25
+ include Matchmaker::DelegateMethod
26
+ include Matchmaker::HaveDbColumn
27
+ include Matchmaker::HaveDbIndex
28
+ include Matchmaker::HaveReadonlyAttribute
29
+ include Matchmaker::HaveSecurePassword
30
+ include Matchmaker::Serialize
31
+ include Matchmaker::Validations
32
+ include ActiveRecordModelSmModelHelper
33
+
34
+
35
+ ### Attribute Accessors ###
36
+ attr_accessor :app_class_name,
37
+ :working_generated_code_line_length
38
+
39
+
40
+ ### Methods ###
41
+ def initialize(app_class_name, app_active_record_descendants_names, code_line_length)
42
+ @app_class_name = app_class_name
43
+ @app_active_record_descendants_names = app_active_record_descendants_names
44
+ @working_generated_code_line_length = code_line_length
45
+ end
46
+
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,206 @@
1
+ require 'model/active_record/options_definition'
2
+
3
+ module ShouldaMatchmakers
4
+ module Model
5
+ module ActiveRecord
6
+ module ActiveRecordModelSmModelHelper
7
+
8
+
9
+ def compose_extended_model_file_path(app_class_name)
10
+ Rails.root.join("app", "models").to_s + "/" + app_class_name.underscore.concat(".rb")
11
+ end
12
+
13
+ def extract_validators(app_class_name, validator_type)
14
+ extracted_validators = app_class_name.constantize.validators.select do |validator|
15
+ validator.class.to_s == validator_type.to_s
16
+ end
17
+ extracted_validators.flatten
18
+ end
19
+
20
+ def conditional_options_exist(validator_options)
21
+ if validator_options.key?(:if) || validator_options.key?(:unless)
22
+ true
23
+ else
24
+ false
25
+ end
26
+ end
27
+
28
+ def parse_validator_options(validator_options)
29
+ non_conditional_options = validator_options
30
+ if validator_options.key?(:if)
31
+ if_option_values = non_conditional_options.delete(:if)
32
+ if_option_values = [if_option_values] if !if_option_values.is_a?(Array)
33
+ else
34
+ if_option_values = []
35
+ end
36
+ if validator_options.key?(:unless)
37
+ unless_option_values = non_conditional_options.delete(:unless)
38
+ unless_option_values = [unless_option_values] if !unless_option_values.is_a?(Array)
39
+ else
40
+ unless_option_values = []
41
+ end
42
+ { non_conditional_options: non_conditional_options, if_option_values: if_option_values, unless_option_values: unless_option_values }
43
+ end
44
+
45
+ def order_options(options)
46
+ options_unordered = options.dup
47
+ options_ordered = {}
48
+ options_ordered = options_ordered.merge({ :in=>options_unordered.delete(:in) }) if options_unordered.include?(:in)
49
+ options_ordered = options_ordered.merge({ :minimum=>options_unordered.delete(:minimum) }) if options_unordered.include?(:minimum)
50
+ options_ordered = options_ordered.merge({ :maximum=>options_unordered.delete(:maximum) }) if options_unordered.include?(:maximum)
51
+ options_ordered.merge(options_unordered)
52
+ end
53
+
54
+ def all_option_values_are_symbols(option_values)
55
+ option_values_are_symbols = true
56
+ if option_values.present?
57
+ option_values.each do |option_value|
58
+ if !option_value.is_a?(Symbol)
59
+ option_values_are_symbols = false
60
+ end
61
+ end
62
+ end
63
+ option_values_are_symbols
64
+ end
65
+
66
+ def get_possible_true_false_permutations(validator_options)
67
+ number_of_conditional_option_values = validator_options[:if_option_values].size +
68
+ validator_options[:unless_option_values].size
69
+ [true, false].repeated_permutation(number_of_conditional_option_values).to_a
70
+ end
71
+
72
+ def get_validating_true_false_permutation(validator_options)
73
+ validating_permutation = []
74
+ validator_options[:if_option_values].size.times do |n|
75
+ validating_permutation << true
76
+ end
77
+ validator_options[:unless_option_values].size.times do |n|
78
+ validating_permutation << false
79
+ end
80
+ validating_permutation
81
+ end
82
+
83
+ def get_options_string(options)
84
+ options_hash = ::ShouldaMatchmakers::Model::ActiveRecord::OptionsDefinition.new.options_hash
85
+ options_string = ""
86
+ options.map do |option_key, option_value|
87
+ if options_hash.key?(option_key)
88
+ option_string = options_hash[option_key].to_s
89
+ option_value_refined = apply_option_value_qualifiers(option_value, option_string)
90
+ option_string = option_string.gsub(/\s*\{\s*/,"").gsub(/\s*\}\s*/,"").gsub(/option_value(?:\.[a-zA-Z0-9_]+)*/, option_value_refined)
91
+ options_string.concat("." + option_string)
92
+ end
93
+ end
94
+ options_string
95
+ end
96
+
97
+ def apply_option_value_qualifiers(option_value, association_option_string)
98
+ option_value_refined = option_value
99
+ option_value_qualifiers = association_option_string.scan(/(?: option_value|\.[a-zA-Z0-9_]+)(\.[a-zA-Z0-9_]+)/)
100
+ option_value_qualifiers.each do |option_value_qualifier|
101
+ case option_value_qualifier
102
+ when ".first"
103
+ option_value_refined = option_value_refined.first
104
+ when ".last"
105
+ option_value_refined = option_value_refined.last
106
+ when ".to_s"
107
+ option_value_refined = option_value_refined.to_s
108
+ end
109
+ end
110
+ option_value_refined.to_s
111
+ end
112
+
113
+ def compose_conditional_validating_context_string(validator_options)
114
+ validating_context_string = " context \""
115
+ conditional_option_values = validator_options[:if_option_values] + validator_options[:unless_option_values]
116
+ conditional_option_values.each_with_index do |option_value, cov_index|
117
+ if cov_index < validator_options[:if_option_values].size
118
+ validating_context_string.concat("if #{ option_value.to_s.chomp('?')} and ")
119
+ else
120
+ validating_context_string.concat("unless #{ option_value.to_s.chomp('?')} and ")
121
+ end
122
+ end
123
+ validating_context_string.chomp!(" and ").concat("\" do\n")
124
+ end
125
+
126
+ def compose_conditional_non_validating_context_string(validator_options, non_validating_permutation)
127
+ non_validating_context_string = " context \""
128
+ conditional_option_values = validator_options[:if_option_values] + validator_options[:unless_option_values]
129
+ conditional_option_values.each_with_index do |conditional_option_value, cov_index|
130
+ if cov_index < validator_options[:if_option_values].size
131
+ non_validating_context_string.concat(get_if_context_condition(conditional_option_value, non_validating_permutation[cov_index]))
132
+ else
133
+ non_validating_context_string.concat(get_unless_context_condition(conditional_option_value, non_validating_permutation[cov_index]))
134
+ end
135
+ end
136
+ non_validating_context_string.chomp!(" and ").concat("\" do\n")
137
+ end
138
+
139
+ def get_if_context_condition(option_value, permutation_boolean_value_for_option)
140
+ if permutation_boolean_value_for_option
141
+ if_context_condition = "if #{ option_value.to_s.chomp('?')} and "
142
+ else
143
+ if_context_condition = "if not #{ option_value.to_s.chomp('?')} and "
144
+ end
145
+ if_context_condition
146
+ end
147
+
148
+ def get_unless_context_condition(option_value, permutation_boolean_value_for_option)
149
+ if permutation_boolean_value_for_option
150
+ unless_context_condition = "if (unless not) #{ option_value.to_s.chomp('?')} and "
151
+ else
152
+ unless_context_condition = "if not (unless) #{ option_value.to_s.chomp('?')} and "
153
+ end
154
+ unless_context_condition
155
+ end
156
+
157
+ def compose_conditional_before_strings(validator_options, conditional_options_permutation)
158
+ conditional_before_strings = ""
159
+ conditional_option_values = validator_options[:if_option_values] + validator_options[:unless_option_values]
160
+ conditional_option_values.each_with_index do |conditional_option_value, cov_index|
161
+ conditional_before_strings.concat(" before { allow(subject).to receive(:#{ conditional_option_value }).and_return(#{ conditional_options_permutation[cov_index] }) }\n")
162
+ end
163
+ conditional_before_strings
164
+ end
165
+
166
+ def append_element(element, element_set)
167
+ if element.present?
168
+ element_set << element
169
+ end
170
+ element_set
171
+ end
172
+
173
+ def adjust_conditional_test_indentation(conditional_test)
174
+ if conditional_test.include?("\n")
175
+ conditional_test.sub(" it do\n","\n it do\n").
176
+ sub("it do\n ","it do\n ").
177
+ gsub(").\n ",").\n ").
178
+ sub("\n end","\n end")
179
+ else
180
+ conditional_test.sub(" it {", "\n it {")
181
+ end
182
+ end
183
+
184
+ def format_tests(tests)
185
+ formatted_tests = properly_line_space_tests(tests)
186
+ formatted_tests.flatten.compact.uniq.join("\n")
187
+ end
188
+
189
+ def properly_line_space_tests(tests)
190
+ tests_properly_line_spaced = []
191
+ previous_test = ""
192
+ tests.each do |test|
193
+ if (test.include?("\n") && previous_test.present?) ||
194
+ (!test.include?("\n") && previous_test.include?("\n"))
195
+ test = "\n" + test
196
+ end
197
+ tests_properly_line_spaced << test
198
+ previous_test = test
199
+ end
200
+ tests_properly_line_spaced
201
+ end
202
+
203
+ end
204
+ end
205
+ end
206
+ end