shoulda_matchmakers 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/Rakefile +21 -0
- data/lib/controller/action_controller/action_controller_controller_sm_model.rb +53 -0
- data/lib/controller/action_controller/action_controller_controller_sm_model_helper.rb +73 -0
- data/lib/controller/action_controller/matchmakers/callbacks.rb +56 -0
- data/lib/controller/action_controller/matchmakers/filter_param.rb +69 -0
- data/lib/controller/action_controller/matchmakers/permit.rb +510 -0
- data/lib/controller/action_controller/matchmakers/redirect_to.rb +126 -0
- data/lib/controller/action_controller/matchmakers/render_template.rb +198 -0
- data/lib/controller/action_controller/matchmakers/render_with_layout.rb +72 -0
- data/lib/controller/action_controller/matchmakers/rescue_from.rb +96 -0
- data/lib/controller/action_controller/matchmakers/respond_with.rb +71 -0
- data/lib/controller/action_controller/matchmakers/route.rb +586 -0
- data/lib/controller/action_controller/matchmakers/set_flash.rb +136 -0
- data/lib/controller/action_controller/matchmakers/set_session.rb +115 -0
- data/lib/controller/action_controller/permitted_params_definition.rb +60 -0
- data/lib/generators/shoulda_matchmakers/controller_matcher_generator.rb +87 -0
- data/lib/generators/shoulda_matchmakers/controller_matcher_generator_helper.rb +92 -0
- data/lib/generators/shoulda_matchmakers/factory_generator.rb +86 -0
- data/lib/generators/shoulda_matchmakers/install_generator.rb +10 -0
- data/lib/generators/shoulda_matchmakers/model_matcher_generator.rb +87 -0
- data/lib/generators/shoulda_matchmakers/model_matcher_generator_helper.rb +107 -0
- data/lib/model/active_record/active_record_model_sm_model.rb +50 -0
- data/lib/model/active_record/active_record_model_sm_model_helper.rb +206 -0
- data/lib/model/active_record/factory_sm_model.rb +28 -0
- data/lib/model/active_record/factory_sm_model_helper.rb +124 -0
- data/lib/model/active_record/matchmakers/accept_nested_attributes_for.rb +66 -0
- data/lib/model/active_record/matchmakers/allow_value.rb +137 -0
- data/lib/model/active_record/matchmakers/associations.rb +52 -0
- data/lib/model/active_record/matchmakers/define_enum_for.rb +53 -0
- data/lib/model/active_record/matchmakers/delegate_method.rb +101 -0
- data/lib/model/active_record/matchmakers/have_db_column.rb +33 -0
- data/lib/model/active_record/matchmakers/have_db_index.rb +39 -0
- data/lib/model/active_record/matchmakers/have_readonly_attribute.rb +32 -0
- data/lib/model/active_record/matchmakers/have_secure_password.rb +32 -0
- data/lib/model/active_record/matchmakers/serialize.rb +67 -0
- data/lib/model/active_record/matchmakers/validations.rb +169 -0
- data/lib/model/active_record/options_definition.rb +160 -0
- data/lib/shoulda_matchmakers.rb +48 -0
- data/lib/shoulda_matchmakers/version.rb +3 -0
- data/lib/support/command_line_interface.rb +100 -0
- data/lib/support/controller_generator.rb +198 -0
- data/lib/support/indefinite_article.rb +70 -0
- data/lib/support/to_discard/belong_to.rb +94 -0
- data/lib/support/to_discard/have_and_belong_to_many.rb +83 -0
- data/lib/support/to_discard/have_many.rb +96 -0
- data/lib/support/to_discard/have_one.rb +98 -0
- data/lib/support/to_discard/permit_refactor.rb +270 -0
- data/lib/support/to_discard/render_template_new.rb +204 -0
- data/lib/support/to_discard/render_template_reconstruction.rb +188 -0
- data/lib/support/to_discard/use_around_action.rb +20 -0
- data/lib/support/to_discard/use_before_action.rb +20 -0
- data/lib/support/to_discard/validate_absence_of.rb +16 -0
- data/lib/support/to_discard/validate_acceptance_of.rb +16 -0
- data/lib/support/to_discard/validate_confirmation_of.rb +16 -0
- data/lib/support/to_discard/validate_exclusion_of.rb +145 -0
- data/lib/support/to_discard/validate_inclusion_of.rb +94 -0
- data/lib/support/to_discard/validate_length_of.rb +16 -0
- data/lib/support/to_discard/validate_numericality_of.rb +16 -0
- data/lib/support/to_discard/validate_presence_of.rb +16 -0
- data/lib/support/to_discard/validate_uniqueness_of.rb +16 -0
- data/lib/support/to_discard/validation_old.rb +37 -0
- data/lib/support/to_discard/validations.rb +41 -0
- data/lib/support/to_discard/validations_conditional.rb +146 -0
- data/lib/support/trace_debug_lines.txt +319 -0
- data/lib/support/util.rb +15 -0
- data/lib/templates/controller/action_controller/controller_spec_template.haml +146 -0
- data/lib/templates/factory/active_record/factory_template.haml +13 -0
- data/lib/templates/model/active_record/model_spec_template.haml +233 -0
- data/lib/templates/shoulda_matchmakers.rb +112 -0
- 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
|