shoulda_matchmakers 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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