rails_best_practices 1.19.2 → 1.20.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.gitignore +0 -1
- data/.travis.yml +2 -3
- data/CHANGELOG.md +7 -7
- data/Gemfile +3 -5
- data/Gemfile.lock +125 -0
- data/Guardfile +2 -0
- data/README.md +6 -6
- data/Rakefile +2 -17
- data/assets/result.html.erb +2 -0
- data/lib/rails_best_practices.rb +3 -2
- data/lib/rails_best_practices/analyzer.rb +61 -49
- data/lib/rails_best_practices/cli.rb +22 -0
- data/lib/rails_best_practices/command.rb +1 -131
- data/lib/rails_best_practices/core/check.rb +64 -56
- data/lib/rails_best_practices/core/checks_loader.rb +24 -23
- data/lib/rails_best_practices/core/configs.rb +1 -2
- data/lib/rails_best_practices/core/controllers.rb +1 -2
- data/lib/rails_best_practices/core/error.rb +1 -1
- data/lib/rails_best_practices/core/helpers.rb +1 -2
- data/lib/rails_best_practices/core/mailers.rb +1 -2
- data/lib/rails_best_practices/core/methods.rb +27 -21
- data/lib/rails_best_practices/core/model_associations.rb +10 -5
- data/lib/rails_best_practices/core/models.rb +1 -2
- data/lib/rails_best_practices/core/modules.rb +1 -1
- data/lib/rails_best_practices/core/routes.rb +2 -2
- data/lib/rails_best_practices/core/runner.rb +67 -73
- data/lib/rails_best_practices/lexicals/long_line_check.rb +7 -3
- data/lib/rails_best_practices/option_parser.rb +156 -0
- data/lib/rails_best_practices/prepares.rb +1 -1
- data/lib/rails_best_practices/prepares/controller_prepare.rb +24 -17
- data/lib/rails_best_practices/prepares/gemfile_prepare.rb +2 -2
- data/lib/rails_best_practices/prepares/helper_prepare.rb +6 -1
- data/lib/rails_best_practices/prepares/initializer_prepare.rb +3 -3
- data/lib/rails_best_practices/prepares/mailer_prepare.rb +2 -1
- data/lib/rails_best_practices/prepares/model_prepare.rb +63 -23
- data/lib/rails_best_practices/prepares/route_prepare.rb +28 -21
- data/lib/rails_best_practices/prepares/schema_prepare.rb +1 -1
- data/lib/rails_best_practices/reviews/add_model_virtual_attribute_review.rb +38 -34
- data/lib/rails_best_practices/reviews/always_add_db_index_review.rb +94 -89
- data/lib/rails_best_practices/reviews/check_destroy_return_value_review.rb +15 -5
- data/lib/rails_best_practices/reviews/check_save_return_value_review.rb +20 -8
- data/lib/rails_best_practices/reviews/default_scope_is_evil_review.rb +1 -1
- data/lib/rails_best_practices/reviews/dry_bundler_in_capistrano_review.rb +1 -1
- data/lib/rails_best_practices/reviews/hash_syntax_review.rb +16 -16
- data/lib/rails_best_practices/reviews/isolate_seed_data_review.rb +12 -12
- data/lib/rails_best_practices/reviews/keep_finders_on_their_own_model_review.rb +10 -11
- data/lib/rails_best_practices/reviews/law_of_demeter_review.rb +25 -24
- data/lib/rails_best_practices/reviews/move_code_into_controller_review.rb +4 -4
- data/lib/rails_best_practices/reviews/move_code_into_helper_review.rb +9 -10
- data/lib/rails_best_practices/reviews/move_finder_to_named_scope_review.rb +10 -11
- data/lib/rails_best_practices/reviews/needless_deep_nesting_review.rb +24 -22
- data/lib/rails_best_practices/reviews/not_rescue_exception_review.rb +1 -1
- data/lib/rails_best_practices/reviews/not_use_default_route_review.rb +1 -2
- data/lib/rails_best_practices/reviews/not_use_time_ago_in_words_review.rb +1 -1
- data/lib/rails_best_practices/reviews/overuse_route_customizations_review.rb +8 -8
- data/lib/rails_best_practices/reviews/protect_mass_assignment_review.rb +35 -32
- data/lib/rails_best_practices/reviews/remove_empty_helpers_review.rb +4 -4
- data/lib/rails_best_practices/reviews/remove_unused_methods_in_controllers_review.rb +26 -19
- data/lib/rails_best_practices/reviews/remove_unused_methods_in_helpers_review.rb +12 -10
- data/lib/rails_best_practices/reviews/remove_unused_methods_in_models_review.rb +38 -18
- data/lib/rails_best_practices/reviews/replace_complex_creation_with_factory_method_review.rb +11 -11
- data/lib/rails_best_practices/reviews/restrict_auto_generated_routes_review.rb +77 -74
- data/lib/rails_best_practices/reviews/review.rb +2 -1
- data/lib/rails_best_practices/reviews/simplify_render_in_controllers_review.rb +2 -3
- data/lib/rails_best_practices/reviews/simplify_render_in_views_review.rb +12 -12
- data/lib/rails_best_practices/reviews/use_before_filter_review.rb +18 -15
- data/lib/rails_best_practices/reviews/use_model_association_review.rb +15 -15
- data/lib/rails_best_practices/reviews/use_multipart_alternative_as_content_type_of_email_review.rb +24 -22
- data/lib/rails_best_practices/reviews/use_observer_review.rb +28 -28
- data/lib/rails_best_practices/reviews/use_parentheses_in_method_def_review.rb +6 -6
- data/lib/rails_best_practices/reviews/use_query_attribute_review.rb +68 -66
- data/lib/rails_best_practices/reviews/use_say_with_time_in_migrations_review.rb +9 -8
- data/lib/rails_best_practices/reviews/use_scope_access_review.rb +16 -14
- data/lib/rails_best_practices/reviews/use_turbo_sprockets_rails3_review.rb +2 -1
- data/lib/rails_best_practices/version.rb +1 -1
- data/rails_best_practices.gemspec +38 -43
- data/spec/fixtures/lib/rails_best_practices/plugins/reviews/not_use_rails_root_review.rb +1 -2
- data/spec/rails_best_practices/analyzer_spec.rb +73 -42
- data/spec/rails_best_practices/core/check_spec.rb +5 -5
- data/spec/rails_best_practices/core/checks_loader_spec.rb +3 -3
- data/spec/rails_best_practices/core/configs_spec.rb +1 -1
- data/spec/rails_best_practices/core/controllers_spec.rb +1 -1
- data/spec/rails_best_practices/core/error_spec.rb +21 -18
- data/spec/rails_best_practices/core/except_methods_spec.rb +7 -7
- data/spec/rails_best_practices/core/gems_spec.rb +4 -4
- data/spec/rails_best_practices/core/helpers_spec.rb +1 -1
- data/spec/rails_best_practices/core/klasses_spec.rb +3 -3
- data/spec/rails_best_practices/core/mailers_spec.rb +1 -1
- data/spec/rails_best_practices/core/methods_spec.rb +6 -6
- data/spec/rails_best_practices/core/model_associations_spec.rb +10 -6
- data/spec/rails_best_practices/core/model_attributes_spec.rb +4 -4
- data/spec/rails_best_practices/core/models_spec.rb +1 -1
- data/spec/rails_best_practices/core/modules_spec.rb +5 -5
- data/spec/rails_best_practices/core/routes_spec.rb +5 -5
- data/spec/rails_best_practices/core/runner_spec.rb +9 -7
- data/spec/rails_best_practices/core_ext/erubis_spec.rb +10 -10
- data/spec/rails_best_practices/lexicals/long_line_check_spec.rb +32 -31
- data/spec/rails_best_practices/lexicals/remove_tab_check_spec.rb +6 -6
- data/spec/rails_best_practices/lexicals/remove_trailing_whitespace_check_spec.rb +6 -6
- data/spec/rails_best_practices/prepares/config_prepare_spec.rb +2 -2
- data/spec/rails_best_practices/prepares/controller_prepare_spec.rb +18 -10
- data/spec/rails_best_practices/prepares/gemfile_prepare_spec.rb +17 -17
- data/spec/rails_best_practices/prepares/helper_prepare_spec.rb +3 -3
- data/spec/rails_best_practices/prepares/initializer_prepare_spec.rb +3 -3
- data/spec/rails_best_practices/prepares/mailer_prepare_spec.rb +2 -2
- data/spec/rails_best_practices/prepares/model_prepare_spec.rb +79 -43
- data/spec/rails_best_practices/prepares/route_prepare_spec.rb +141 -76
- data/spec/rails_best_practices/prepares/schema_prepare_spec.rb +2 -2
- data/spec/rails_best_practices/reviews/add_model_virtual_attribute_review_spec.rb +18 -12
- data/spec/rails_best_practices/reviews/always_add_db_index_review_spec.rb +28 -22
- data/spec/rails_best_practices/reviews/check_destroy_return_value_review_spec.rb +15 -13
- data/spec/rails_best_practices/reviews/check_save_return_value_review_spec.rb +31 -21
- data/spec/rails_best_practices/reviews/default_scope_is_evil_review_spec.rb +6 -6
- data/spec/rails_best_practices/reviews/dry_bundler_in_capistrano_review_spec.rb +5 -5
- data/spec/rails_best_practices/reviews/hash_syntax_review_spec.rb +13 -13
- data/spec/rails_best_practices/reviews/isolate_seed_data_review_spec.rb +7 -7
- data/spec/rails_best_practices/reviews/keep_finders_on_their_own_model_review_spec.rb +9 -9
- data/spec/rails_best_practices/reviews/law_of_demeter_review_spec.rb +29 -22
- data/spec/rails_best_practices/reviews/move_code_into_controller_review_spec.rb +6 -6
- data/spec/rails_best_practices/reviews/move_code_into_helper_review_spec.rb +11 -6
- data/spec/rails_best_practices/reviews/move_code_into_model_review_spec.rb +32 -22
- data/spec/rails_best_practices/reviews/move_finder_to_named_scope_review_spec.rb +7 -7
- data/spec/rails_best_practices/reviews/move_model_logic_into_model_review_spec.rb +9 -7
- data/spec/rails_best_practices/reviews/needless_deep_nesting_review_spec.rb +9 -9
- data/spec/rails_best_practices/reviews/not_rescue_exception_review_spec.rb +9 -9
- data/spec/rails_best_practices/reviews/not_use_default_route_review_spec.rb +5 -5
- data/spec/rails_best_practices/reviews/not_use_time_ago_in_words_review_spec.rb +7 -7
- data/spec/rails_best_practices/reviews/overuse_route_customizations_review_spec.rb +7 -7
- data/spec/rails_best_practices/reviews/protect_mass_assignment_review_spec.rb +24 -17
- data/spec/rails_best_practices/reviews/remove_empty_helpers_review_spec.rb +6 -6
- data/spec/rails_best_practices/reviews/remove_unused_methods_in_controllers_review_spec.rb +64 -31
- data/spec/rails_best_practices/reviews/remove_unused_methods_in_helpers_review_spec.rb +21 -14
- data/spec/rails_best_practices/reviews/remove_unused_methods_in_models_review_spec.rb +57 -53
- data/spec/rails_best_practices/reviews/replace_complex_creation_with_factory_method_review_spec.rb +10 -8
- data/spec/rails_best_practices/reviews/replace_instance_variable_with_local_variable_review_spec.rb +20 -14
- data/spec/rails_best_practices/reviews/restrict_auto_generated_routes_review_spec.rb +54 -31
- data/spec/rails_best_practices/reviews/simplify_render_in_controllers_review_spec.rb +9 -9
- data/spec/rails_best_practices/reviews/simplify_render_in_views_review_spec.rb +13 -13
- data/spec/rails_best_practices/reviews/use_before_filter_review_spec.rb +11 -9
- data/spec/rails_best_practices/reviews/use_model_association_review_spec.rb +7 -7
- data/spec/rails_best_practices/reviews/use_multipart_alternative_as_content_type_of_email_review_spec.rb +35 -31
- data/spec/rails_best_practices/reviews/use_observer_review_spec.rb +6 -6
- data/spec/rails_best_practices/reviews/use_parentheses_in_method_def_review_spec.rb +10 -8
- data/spec/rails_best_practices/reviews/use_query_attribute_review_spec.rb +31 -24
- data/spec/rails_best_practices/reviews/use_say_with_time_in_migrations_review_spec.rb +15 -11
- data/spec/rails_best_practices/reviews/use_scope_access_review_spec.rb +14 -14
- data/spec/rails_best_practices/reviews/use_turbo_sprockets_rails3_review_spec.rb +61 -59
- metadata +16 -18
@@ -3,6 +3,7 @@
|
|
3
3
|
module RailsBestPractices
|
4
4
|
module Prepares
|
5
5
|
# Remember controllers and controller methods
|
6
|
+
|
6
7
|
class ControllerPrepare < Core::Check
|
7
8
|
include Core::Check::Classable
|
8
9
|
include Core::Check::InheritedResourcesable
|
@@ -24,43 +25,42 @@ module RailsBestPractices
|
|
24
25
|
# also check if the controller is inherit from InheritedResources::Base.
|
25
26
|
add_callback :start_class do |_node|
|
26
27
|
@controllers << @klass
|
27
|
-
|
28
|
-
|
29
|
-
end
|
28
|
+
@current_controller_name = @klass.to_s
|
29
|
+
@actions = DEFAULT_ACTIONS if @inherited_resources
|
30
30
|
end
|
31
31
|
|
32
32
|
# remember the action names at the end of class node if the controller is a InheritedResources.
|
33
33
|
add_callback :end_class do |node|
|
34
|
-
if @inherited_resources && 'ApplicationController'
|
34
|
+
if @inherited_resources && @current_controller_name != 'ApplicationController'
|
35
35
|
@actions.each do |action|
|
36
|
-
@methods.add_method(
|
36
|
+
@methods.add_method(
|
37
|
+
@current_controller_name,
|
38
|
+
action,
|
39
|
+
'file' => node.file, 'line_number' => node.line_number
|
40
|
+
)
|
37
41
|
end
|
38
42
|
end
|
39
43
|
end
|
40
44
|
|
41
45
|
# check if there is a DSL call inherit_resources.
|
42
46
|
add_callback :start_var_ref do |_node|
|
43
|
-
if @inherited_resources
|
44
|
-
@actions = DEFAULT_ACTIONS
|
45
|
-
end
|
47
|
+
@actions = DEFAULT_ACTIONS if @inherited_resources
|
46
48
|
end
|
47
49
|
|
48
50
|
# check if there is a DSL call inherit_resources.
|
49
51
|
add_callback :start_vcall do |_node|
|
50
|
-
if @inherited_resources
|
51
|
-
@actions = DEFAULT_ACTIONS
|
52
|
-
end
|
52
|
+
@actions = DEFAULT_ACTIONS if @inherited_resources
|
53
53
|
end
|
54
54
|
|
55
55
|
# restrict actions for inherited_resources
|
56
56
|
add_callback :start_command do |node|
|
57
|
-
if
|
57
|
+
if node.message.to_s == 'include'
|
58
58
|
@helpers.add_module_descendant(node.arguments.all.first.to_s, current_class_name)
|
59
|
-
elsif @inherited_resources &&
|
60
|
-
if
|
59
|
+
elsif @inherited_resources && node.message.to_s == 'actions'
|
60
|
+
if node.arguments.all.first.to_s == 'all'
|
61
61
|
@actions = DEFAULT_ACTIONS
|
62
62
|
option_argument = node.arguments.all[1]
|
63
|
-
if option_argument &&
|
63
|
+
if option_argument && option_argument.sexp_type == :bare_assoc_hash && option_argument.hash_value('except')
|
64
64
|
@actions -= option_argument.hash_value('except').to_object
|
65
65
|
end
|
66
66
|
else
|
@@ -83,14 +83,21 @@ module RailsBestPractices
|
|
83
83
|
# }
|
84
84
|
add_callback :start_def do |node|
|
85
85
|
method_name = node.method_name.to_s
|
86
|
-
@methods.add_method(
|
86
|
+
@methods.add_method(
|
87
|
+
current_class_name,
|
88
|
+
method_name,
|
89
|
+
{ 'file' => node.file, 'line_number' => node.line_number },
|
90
|
+
current_access_control
|
91
|
+
)
|
87
92
|
end
|
88
93
|
|
89
94
|
# ask Reviews::RemoveUnusedMoethodsInHelperReview to check the controllers who include helpers.
|
90
95
|
add_callback :after_check do
|
91
96
|
descendants = @helpers.map(&:descendants).flatten
|
92
97
|
if descendants.present?
|
93
|
-
Reviews::RemoveUnusedMethodsInHelpersReview.interesting_files *descendants.map { |descendant|
|
98
|
+
Reviews::RemoveUnusedMethodsInHelpersReview.interesting_files *descendants.map { |descendant|
|
99
|
+
/#{descendant.underscore}/
|
100
|
+
}
|
94
101
|
end
|
95
102
|
end
|
96
103
|
end
|
@@ -10,10 +10,10 @@ module RailsBestPractices
|
|
10
10
|
@gems = Prepares.gems
|
11
11
|
end
|
12
12
|
|
13
|
-
def check(
|
13
|
+
def check(_filename, content)
|
14
14
|
content.split("\n").each do |line|
|
15
15
|
if line =~ /([^ ]+) \((\d.*)\)/
|
16
|
-
@gems << Core::Gem.new(
|
16
|
+
@gems << Core::Gem.new(Regexp.last_match(1), Regexp.last_match(2))
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
@@ -32,7 +32,12 @@ module RailsBestPractices
|
|
32
32
|
add_callback :start_def do |node|
|
33
33
|
if node.file =~ HELPER_FILES
|
34
34
|
method_name = node.method_name.to_s
|
35
|
-
@methods.add_method(
|
35
|
+
@methods.add_method(
|
36
|
+
current_module_name,
|
37
|
+
method_name,
|
38
|
+
{ 'file' => node.file, 'line_number' => node.line_number },
|
39
|
+
current_access_control
|
40
|
+
)
|
36
41
|
end
|
37
42
|
end
|
38
43
|
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
module RailsBestPractices
|
4
4
|
module Prepares
|
5
5
|
# Check all initializers
|
6
|
+
|
6
7
|
class InitializerPrepare < Core::Check
|
7
8
|
interesting_nodes :method_add_arg, :class
|
8
9
|
interesting_files INITIALIZER_FILES
|
@@ -21,9 +22,8 @@ module RailsBestPractices
|
|
21
22
|
# check if the node is
|
22
23
|
# ActiveRecord::Base.send(:include, ActiveModel::ForbiddenAttributesProtection)
|
23
24
|
def include_forbidden_attributes_protection?(node)
|
24
|
-
'ActiveRecord::Base'
|
25
|
-
|
26
|
-
['include', 'ActiveModel::ForbiddenAttributesProtection'] == node.arguments.all.map(&:to_s)
|
25
|
+
node.receiver.to_s == 'ActiveRecord::Base' && node.message.to_s == 'send' &&
|
26
|
+
node.arguments.all.map(&:to_s) == ['include', 'ActiveModel::ForbiddenAttributesProtection']
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
module RailsBestPractices
|
4
4
|
module Prepares
|
5
5
|
# Remember the mailer names.
|
6
|
+
|
6
7
|
class MailerPrepare < Core::Check
|
7
8
|
include Core::Check::Classable
|
8
9
|
|
@@ -18,7 +19,7 @@ module RailsBestPractices
|
|
18
19
|
# if it is a subclass of ActionMailer::Base,
|
19
20
|
# then remember its class name.
|
20
21
|
add_callback :start_class do |_node|
|
21
|
-
if 'ActionMailer::Base'
|
22
|
+
if current_extend_class_name == 'ActionMailer::Base'
|
22
23
|
@mailers << @klass
|
23
24
|
end
|
24
25
|
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
module RailsBestPractices
|
4
4
|
module Prepares
|
5
5
|
# Remember models and model associations.
|
6
|
+
|
6
7
|
class ModelPrepare < Core::Check
|
7
8
|
include Core::Check::Classable
|
8
9
|
include Core::Check::Accessable
|
@@ -10,7 +11,17 @@ module RailsBestPractices
|
|
10
11
|
interesting_nodes :class, :def, :defs, :command, :alias
|
11
12
|
interesting_files MODEL_FILES
|
12
13
|
|
13
|
-
ASSOCIATION_METHODS = %w[
|
14
|
+
ASSOCIATION_METHODS = %w[
|
15
|
+
belongs_to
|
16
|
+
has_one
|
17
|
+
has_many
|
18
|
+
has_and_belongs_to_many
|
19
|
+
embeds_many
|
20
|
+
embeds_one
|
21
|
+
embedded_in
|
22
|
+
many
|
23
|
+
one
|
24
|
+
].freeze
|
14
25
|
|
15
26
|
def initialize
|
16
27
|
@models = Prepares.models
|
@@ -21,7 +32,7 @@ module RailsBestPractices
|
|
21
32
|
|
22
33
|
# remember the class name.
|
23
34
|
add_callback :start_class do |_node|
|
24
|
-
if 'ActionMailer::Base'
|
35
|
+
if current_extend_class_name != 'ActionMailer::Base'
|
25
36
|
@models << @klass
|
26
37
|
end
|
27
38
|
end
|
@@ -39,11 +50,14 @@ module RailsBestPractices
|
|
39
50
|
# }
|
40
51
|
# }
|
41
52
|
add_callback :start_def do |node|
|
42
|
-
if @klass &&
|
43
|
-
'ActionMailer::Base' != current_extend_class_name &&
|
44
|
-
(classable_modules.empty? || klasses.any?)
|
53
|
+
if @klass && current_extend_class_name != 'ActionMailer::Base' && (classable_modules.empty? || klasses.any?)
|
45
54
|
method_name = node.method_name.to_s
|
46
|
-
@methods.add_method(
|
55
|
+
@methods.add_method(
|
56
|
+
current_class_name,
|
57
|
+
method_name,
|
58
|
+
{ 'file' => node.file, 'line_number' => node.line_number },
|
59
|
+
current_access_control
|
60
|
+
)
|
47
61
|
end
|
48
62
|
end
|
49
63
|
|
@@ -60,9 +74,14 @@ module RailsBestPractices
|
|
60
74
|
# }
|
61
75
|
# }
|
62
76
|
add_callback :start_defs do |node|
|
63
|
-
if @klass && 'ActionMailer::Base'
|
77
|
+
if @klass && current_extend_class_name != 'ActionMailer::Base'
|
64
78
|
method_name = node.method_name.to_s
|
65
|
-
@methods.add_method(
|
79
|
+
@methods.add_method(
|
80
|
+
current_class_name,
|
81
|
+
method_name,
|
82
|
+
{ 'file' => node.file, 'line_number' => node.line_number },
|
83
|
+
current_access_control
|
84
|
+
)
|
66
85
|
end
|
67
86
|
end
|
68
87
|
|
@@ -81,15 +100,31 @@ module RailsBestPractices
|
|
81
100
|
case node.message.to_s
|
82
101
|
when 'named_scope', 'scope', 'alias_method'
|
83
102
|
method_name = node.arguments.all.first.to_s
|
84
|
-
@methods.add_method(
|
103
|
+
@methods.add_method(
|
104
|
+
current_class_name,
|
105
|
+
method_name,
|
106
|
+
{ 'file' => node.file, 'line_number' => node.line_number },
|
107
|
+
current_access_control
|
108
|
+
)
|
85
109
|
when 'alias_method_chain'
|
86
110
|
method, feature = *node.arguments.all.map(&:to_s)
|
87
|
-
@methods.add_method(
|
88
|
-
|
111
|
+
@methods.add_method(
|
112
|
+
current_class_name,
|
113
|
+
"#{method}_with_#{feature}",
|
114
|
+
{ 'file' => node.file, 'line_number' => node.line_number },
|
115
|
+
current_access_control
|
116
|
+
)
|
117
|
+
@methods.add_method(
|
118
|
+
current_class_name,
|
119
|
+
method.to_s,
|
120
|
+
{ 'file' => node.file, 'line_number' => node.line_number },
|
121
|
+
current_access_control
|
122
|
+
)
|
89
123
|
when 'field'
|
90
124
|
arguments = node.arguments.all
|
91
125
|
attribute_name = arguments.first.to_s
|
92
|
-
attribute_type =
|
126
|
+
attribute_type =
|
127
|
+
arguments.last.hash_value('type').present? ? arguments.last.hash_value('type').to_s : 'String'
|
93
128
|
@model_attributes.add_attribute(current_class_name, attribute_name, attribute_type)
|
94
129
|
when 'key'
|
95
130
|
attribute_name, attribute_type = node.arguments.all.map(&:to_s)
|
@@ -102,7 +137,12 @@ module RailsBestPractices
|
|
102
137
|
# check alias node to remembr the alias methods.
|
103
138
|
add_callback :start_alias do |node|
|
104
139
|
method_name = node.new_method.to_s
|
105
|
-
@methods.add_method(
|
140
|
+
@methods.add_method(
|
141
|
+
current_class_name,
|
142
|
+
method_name,
|
143
|
+
{ 'file' => node.file, 'line_number' => node.line_number },
|
144
|
+
current_access_control
|
145
|
+
)
|
106
146
|
end
|
107
147
|
|
108
148
|
# after prepare process, fix incorrect associations' class_name.
|
@@ -122,17 +162,17 @@ module RailsBestPractices
|
|
122
162
|
|
123
163
|
private
|
124
164
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
end
|
133
|
-
association_class ||= association_name.classify
|
134
|
-
@model_associations.add_association(current_class_name, association_name, association_meta, association_class)
|
165
|
+
# remember associations, with class to association names.
|
166
|
+
def remember_association(node)
|
167
|
+
association_meta = node.message.to_s
|
168
|
+
association_name = node.arguments.all.first.to_s
|
169
|
+
arguments_node = node.arguments.all.last
|
170
|
+
if arguments_node.hash_value('class_name').present?
|
171
|
+
association_class = arguments_node.hash_value('class_name').to_s
|
135
172
|
end
|
173
|
+
association_class ||= association_name.classify
|
174
|
+
@model_associations.add_association(current_class_name, association_name, association_meta, association_class)
|
175
|
+
end
|
136
176
|
end
|
137
177
|
end
|
138
178
|
end
|
@@ -27,21 +27,20 @@ module RailsBestPractices
|
|
27
27
|
first_argument = node.arguments.all.first
|
28
28
|
second_argument = node.arguments.all[1]
|
29
29
|
if @controller_names.last
|
30
|
-
if
|
30
|
+
if first_argument.sexp_type == :bare_assoc_hash
|
31
31
|
action_names = [first_argument.hash_values.first.to_s]
|
32
|
-
elsif
|
32
|
+
elsif first_argument.sexp_type == :array
|
33
33
|
action_names = first_argument.array_values.map(&:to_s)
|
34
|
-
elsif
|
35
|
-
if
|
34
|
+
elsif second_argument.try(:sexp_type) == :bare_assoc_hash && second_argument.hash_value('to').present?
|
35
|
+
if second_argument.hash_value('to').sexp_type == :string_literal
|
36
36
|
controller_name, action_name = second_argument.hash_value('to').to_s.split('#')
|
37
37
|
action_names = [action_name]
|
38
38
|
else
|
39
39
|
action_names = [second_argument.hash_value('to').to_s]
|
40
40
|
end
|
41
|
-
elsif
|
42
|
-
|
43
|
-
action_names = node.arguments.all.select
|
44
|
-
{ |arg| :symbol_literal == arg.sexp_type }.map(&:to_s)
|
41
|
+
elsif first_argument.sexp_type == :symbol_literal && second_argument.try(:sexp_type) &&
|
42
|
+
second_argument.sexp_type == :symbol_literal
|
43
|
+
action_names = node.arguments.all.select { |arg| arg.sexp_type == :symbol_literal }.map(&:to_s)
|
45
44
|
else
|
46
45
|
action_names = [first_argument.to_s]
|
47
46
|
end
|
@@ -49,18 +48,18 @@ module RailsBestPractices
|
|
49
48
|
@routes.add_route(current_namespaces, current_controller_name, action_name)
|
50
49
|
end
|
51
50
|
else
|
52
|
-
if
|
51
|
+
if first_argument.sexp_type == :bare_assoc_hash
|
53
52
|
route_node = first_argument.hash_values.first
|
54
53
|
# do not parse redirect block
|
55
|
-
if
|
54
|
+
if route_node.sexp_type != :method_add_arg
|
56
55
|
controller_name, action_name = route_node.to_s.split('#')
|
57
56
|
@routes.add_route(current_namespaces, controller_name.underscore, action_name)
|
58
57
|
end
|
59
|
-
elsif
|
58
|
+
elsif first_argument.sexp_type == :array
|
60
59
|
first_argument.array_values.map(&:to_s).each do |action_node|
|
61
60
|
@routes.add_route(current_namespaces, controller_name, action_node.to_s)
|
62
61
|
end
|
63
|
-
elsif
|
62
|
+
elsif second_argument.try(:sexp_type) == :bare_assoc_hash
|
64
63
|
if second_argument.hash_value('to').present?
|
65
64
|
controller_name, action_name = second_argument.hash_value('to').to_s.split('#')
|
66
65
|
else
|
@@ -78,12 +77,16 @@ module RailsBestPractices
|
|
78
77
|
case options.sexp_type
|
79
78
|
when :bare_assoc_hash
|
80
79
|
if options.hash_value('controller').present?
|
81
|
-
return if
|
80
|
+
return if options.hash_value('controller').sexp_type == :regexp_literal
|
81
|
+
|
82
82
|
controller_name = options.hash_value('controller').to_s
|
83
83
|
action_name = options.hash_value('action').present? ? options.hash_value('action').to_s : '*'
|
84
84
|
@routes.add_route(current_namespaces, controller_name, action_name)
|
85
85
|
else
|
86
|
-
route_node =
|
86
|
+
route_node =
|
87
|
+
options.hash_values.find do |value_node|
|
88
|
+
value_node.sexp_type == :string_literal && value_node.to_s.include?('#')
|
89
|
+
end
|
87
90
|
if route_node.present?
|
88
91
|
controller_name, action_name = route_node.to_s.split('#')
|
89
92
|
@routes.add_route(current_namespaces, controller_name.underscore, action_name)
|
@@ -100,7 +103,10 @@ module RailsBestPractices
|
|
100
103
|
options = node.arguments.all.last
|
101
104
|
case options.sexp_type
|
102
105
|
when :bare_assoc_hash
|
103
|
-
route_node =
|
106
|
+
route_node =
|
107
|
+
options.hash_values.find do |value_node|
|
108
|
+
value_node.sexp_type == :string_literal && value_node.to_s.include?('#')
|
109
|
+
end
|
104
110
|
if route_node.present?
|
105
111
|
controller_name, action_name = route_node.to_s.split('#')
|
106
112
|
@routes.add_route(current_namespaces, controller_name.underscore, action_name)
|
@@ -144,14 +150,15 @@ module RailsBestPractices
|
|
144
150
|
if node.arguments.all.last.hash_value('module').present?
|
145
151
|
@namespaces << node.arguments.all.last.hash_value('module').to_s
|
146
152
|
end
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
153
|
+
@controller_name =
|
154
|
+
if node.arguments.all.last.hash_value('controller').present?
|
155
|
+
[:scope, node.arguments.all.last.hash_value('controller').to_s]
|
156
|
+
else
|
157
|
+
@controller_name.try(:first) == :scope ? @controller_name : nil
|
158
|
+
end
|
152
159
|
when 'with_options'
|
153
160
|
argument = node.arguments.all.last
|
154
|
-
if
|
161
|
+
if argument.sexp_type == :bare_assoc_hash && argument.hash_value('controller').present?
|
155
162
|
@controller_name = [:with_option, argument.hash_value('controller').to_s]
|
156
163
|
end
|
157
164
|
else
|
@@ -46,46 +46,50 @@ module RailsBestPractices
|
|
46
46
|
|
47
47
|
private
|
48
48
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
aref_node = right_value.grep_node(sexp_type: :aref)
|
56
|
-
if aref_node
|
57
|
-
assignments(left_value.receiver.to_s) << { message: left_value.message.to_s, arguments: aref_node.to_s }
|
58
|
-
end
|
59
|
-
end
|
49
|
+
# check an attribute assignment node, if there is a array reference node in the right value of assignment node,
|
50
|
+
# then remember this attribute assignment.
|
51
|
+
def assign(node)
|
52
|
+
left_value = node.left_value
|
53
|
+
right_value = node.right_value
|
54
|
+
return unless left_value.sexp_type == :field && right_value.sexp_type == :call
|
60
55
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
# then this node needs to add a virtual attribute.
|
65
|
-
def call_assignment(node)
|
66
|
-
if ['save', 'save!'].include? node.message.to_s
|
67
|
-
receiver = node.receiver.to_s
|
68
|
-
add_error "add model virtual attribute (for #{receiver})" if params_dup?(assignments(receiver).collect { |h| h[:arguments] })
|
69
|
-
end
|
56
|
+
aref_node = right_value.grep_node(sexp_type: :aref)
|
57
|
+
if aref_node
|
58
|
+
assignments(left_value.receiver.to_s) << { message: left_value.message.to_s, arguments: aref_node.to_s }
|
70
59
|
end
|
60
|
+
end
|
71
61
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
62
|
+
# check a call node with message "save" or "save!",
|
63
|
+
# if there exists an attribute assignment for the receiver of this call node,
|
64
|
+
# and if the arguments of this attribute assignments has duplicated entries (different message and same arguments),
|
65
|
+
# then this node needs to add a virtual attribute.
|
66
|
+
def call_assignment(node)
|
67
|
+
if ['save', 'save!'].include? node.message.to_s
|
68
|
+
receiver = node.receiver.to_s
|
69
|
+
add_error "add model virtual attribute (for #{receiver})" if params_dup?(
|
70
|
+
assignments(receiver).collect { |h| h[:arguments] }
|
71
|
+
)
|
76
72
|
end
|
73
|
+
end
|
77
74
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
end
|
75
|
+
# if the nodes are duplicated.
|
76
|
+
def params_dup?(nodes)
|
77
|
+
return false if nodes.nil?
|
82
78
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
79
|
+
!dups(nodes).empty?
|
80
|
+
end
|
81
|
+
|
82
|
+
# get the assignments of receiver.
|
83
|
+
def assignments(receiver)
|
84
|
+
@assignments[receiver] ||= []
|
85
|
+
end
|
86
|
+
|
87
|
+
# Get the duplicate entries from an Enumerable.
|
88
|
+
#
|
89
|
+
# @return [Enumerable] the duplicate entries.
|
90
|
+
def dups(nodes)
|
91
|
+
nodes.each_with_object({}) { |v, h| h[v] = h[v].to_i + 1 }.reject { |_k, v| v == 1 }.keys
|
92
|
+
end
|
89
93
|
end
|
90
94
|
end
|
91
95
|
end
|