rails_best_practices 1.20.0 → 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 +4 -4
- data/Gemfile +3 -1
- data/Gemfile.lock +30 -26
- data/Guardfile +2 -0
- data/Rakefile +2 -0
- data/lib/rails_best_practices.rb +1 -2
- data/lib/rails_best_practices/analyzer.rb +56 -46
- data/lib/rails_best_practices/core/check.rb +39 -32
- data/lib/rails_best_practices/core/checks_loader.rb +8 -6
- 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 +21 -16
- data/lib/rails_best_practices/core/model_associations.rb +9 -4
- 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 +29 -33
- data/lib/rails_best_practices/lexicals/long_line_check.rb +7 -3
- data/lib/rails_best_practices/option_parser.rb +17 -6
- data/lib/rails_best_practices/prepares.rb +1 -1
- data/lib/rails_best_practices/prepares/controller_prepare.rb +15 -3
- data/lib/rails_best_practices/prepares/gemfile_prepare.rb +1 -1
- data/lib/rails_best_practices/prepares/helper_prepare.rb +6 -1
- data/lib/rails_best_practices/prepares/initializer_prepare.rb +2 -2
- data/lib/rails_best_practices/prepares/mailer_prepare.rb +1 -0
- data/lib/rails_best_practices/prepares/model_prepare.rb +52 -12
- data/lib/rails_best_practices/prepares/route_prepare.rb +16 -10
- data/lib/rails_best_practices/reviews/add_model_virtual_attribute_review.rb +15 -13
- data/lib/rails_best_practices/reviews/always_add_db_index_review.rb +34 -29
- data/lib/rails_best_practices/reviews/check_destroy_return_value_review.rb +14 -5
- data/lib/rails_best_practices/reviews/check_save_return_value_review.rb +19 -8
- data/lib/rails_best_practices/reviews/hash_syntax_review.rb +5 -5
- data/lib/rails_best_practices/reviews/isolate_seed_data_review.rb +4 -4
- data/lib/rails_best_practices/reviews/keep_finders_on_their_own_model_review.rb +7 -8
- data/lib/rails_best_practices/reviews/law_of_demeter_review.rb +6 -6
- data/lib/rails_best_practices/reviews/move_code_into_controller_review.rb +1 -1
- data/lib/rails_best_practices/reviews/move_code_into_helper_review.rb +6 -7
- data/lib/rails_best_practices/reviews/move_finder_to_named_scope_review.rb +7 -8
- data/lib/rails_best_practices/reviews/needless_deep_nesting_review.rb +12 -10
- data/lib/rails_best_practices/reviews/not_use_default_route_review.rb +1 -2
- data/lib/rails_best_practices/reviews/overuse_route_customizations_review.rb +5 -5
- data/lib/rails_best_practices/reviews/protect_mass_assignment_review.rb +5 -2
- data/lib/rails_best_practices/reviews/remove_unused_methods_in_controllers_review.rb +6 -3
- data/lib/rails_best_practices/reviews/remove_unused_methods_in_helpers_review.rb +6 -4
- data/lib/rails_best_practices/reviews/remove_unused_methods_in_models_review.rb +29 -9
- data/lib/rails_best_practices/reviews/replace_complex_creation_with_factory_method_review.rb +3 -3
- data/lib/rails_best_practices/reviews/restrict_auto_generated_routes_review.rb +17 -15
- data/lib/rails_best_practices/reviews/simplify_render_in_controllers_review.rb +1 -2
- data/lib/rails_best_practices/reviews/simplify_render_in_views_review.rb +3 -3
- data/lib/rails_best_practices/reviews/use_before_filter_review.rb +2 -1
- data/lib/rails_best_practices/reviews/use_model_association_review.rb +5 -5
- data/lib/rails_best_practices/reviews/use_multipart_alternative_as_content_type_of_email_review.rb +9 -8
- data/lib/rails_best_practices/reviews/use_observer_review.rb +9 -9
- data/lib/rails_best_practices/reviews/use_query_attribute_review.rb +26 -26
- data/lib/rails_best_practices/reviews/use_say_with_time_in_migrations_review.rb +8 -7
- data/lib/rails_best_practices/reviews/use_scope_access_review.rb +17 -15
- 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 +35 -36
- 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 -21
- 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 +11 -10
- 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 +2 -2
- 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 +138 -77
- 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 +9 -9
- 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 +21 -14
- 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 +26 -16
- 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 -19
- 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 +44 -31
- data/spec/rails_best_practices/reviews/remove_unused_methods_in_helpers_review_spec.rb +17 -12
- data/spec/rails_best_practices/reviews/remove_unused_methods_in_models_review_spec.rb +46 -44
- 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 +16 -10
- 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 +21 -17
- 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 +9 -7
- 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 +10 -8
- metadata +7 -7
@@ -23,9 +23,9 @@ module RailsBestPractices
|
|
23
23
|
# then it should be replaced by simplified syntax.
|
24
24
|
add_callback :start_command do |node|
|
25
25
|
if node.message.to_s == 'render'
|
26
|
-
hash_node =
|
27
|
-
if hash_node && hash_node.sexp_type == :bare_assoc_hash &&
|
28
|
-
|
26
|
+
hash_node = node.arguments.all.first
|
27
|
+
if hash_node && hash_node.sexp_type == :bare_assoc_hash && include_partial?(hash_node) &&
|
28
|
+
valid_hash?(hash_node)
|
29
29
|
add_error 'simplify render in views'
|
30
30
|
end
|
31
31
|
end
|
@@ -12,6 +12,7 @@ module RailsBestPractices
|
|
12
12
|
# Review process:
|
13
13
|
# check all first code line_number in method definitions (actions),
|
14
14
|
# if they are duplicated, then they should be moved to before_filter.
|
15
|
+
|
15
16
|
class UseBeforeFilterReview < Review
|
16
17
|
interesting_nodes :class
|
17
18
|
interesting_files CONTROLLER_FILES
|
@@ -48,7 +49,7 @@ module RailsBestPractices
|
|
48
49
|
|
49
50
|
private
|
50
51
|
|
51
|
-
|
52
|
+
# check method define node, and remember the first sentence.
|
52
53
|
def remember_first_sentence(node)
|
53
54
|
first_sentence = node.body.statements.first
|
54
55
|
return unless first_sentence
|
@@ -43,8 +43,8 @@ module RailsBestPractices
|
|
43
43
|
|
44
44
|
private
|
45
45
|
|
46
|
-
|
47
|
-
|
46
|
+
# check an attribute assignment node, if its message is xxx_id,
|
47
|
+
# then remember the receiver of the attribute assignment in @assignments.
|
48
48
|
def attribute_assignment(node)
|
49
49
|
if node.left_value.message.is_a?(Sexp) && node.left_value.message.to_s =~ /_id$/
|
50
50
|
receiver = node.left_value.receiver.to_s
|
@@ -52,9 +52,9 @@ module RailsBestPractices
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
-
|
56
|
-
|
57
|
-
|
55
|
+
# check a call node with message "save" or "save!",
|
56
|
+
# if the receiver of call node exists in @assignments,
|
57
|
+
# then the attribute assignment should be replaced by using model association.
|
58
58
|
def call_assignment(node)
|
59
59
|
if ['save', 'save!'].include? node.message.to_s
|
60
60
|
receiver = node.receiver.to_s
|
data/lib/rails_best_practices/reviews/use_multipart_alternative_as_content_type_of_email_review.rb
CHANGED
@@ -11,6 +11,7 @@ module RailsBestPractices
|
|
11
11
|
# Review process:
|
12
12
|
# check class node to remember the class name,
|
13
13
|
# and check the method definition nodes to see if the corresponding mailer views exist or not.
|
14
|
+
|
14
15
|
class UseMultipartAlternativeAsContentTypeOfEmailReview < Review
|
15
16
|
interesting_nodes :class, :def
|
16
17
|
interesting_files MAILER_FILES
|
@@ -31,14 +32,14 @@ module RailsBestPractices
|
|
31
32
|
|
32
33
|
private
|
33
34
|
|
34
|
-
|
35
|
-
|
36
|
-
|
35
|
+
# check if rails's syntax mailer views are canonical.
|
36
|
+
#
|
37
|
+
# @param [String] name method name in action_mailer
|
37
38
|
def rails_canonical_mailer_views?(name); end
|
38
39
|
|
39
|
-
|
40
|
-
|
41
|
-
|
40
|
+
# check if rails3's syntax mailer views are canonical.
|
41
|
+
#
|
42
|
+
# @param [String] name method name in action_mailer
|
42
43
|
def rails3_canonical_mailer_views?(name)
|
43
44
|
return true if mailer_files(name).empty?
|
44
45
|
return true if mailer_files(name).none? { |filename| filename.index 'html' }
|
@@ -47,12 +48,12 @@ module RailsBestPractices
|
|
47
48
|
mailer_files(name).any? { |filename| filename.index 'text' }
|
48
49
|
end
|
49
50
|
|
50
|
-
|
51
|
+
# all mail view files for a method name.
|
51
52
|
def mailer_files(name)
|
52
53
|
Dir.entries(mailer_directory) { |filename| filename.index name.to_s }
|
53
54
|
end
|
54
55
|
|
55
|
-
|
56
|
+
# the view directory of mailer.
|
56
57
|
def mailer_directory
|
57
58
|
File.join(Core::Runner.base_path, "app/views/#{@klazz_name.to_s.underscore}")
|
58
59
|
end
|
@@ -49,8 +49,8 @@ module RailsBestPractices
|
|
49
49
|
|
50
50
|
private
|
51
51
|
|
52
|
-
|
53
|
-
|
52
|
+
# check a command node, if it is a callback definition, such as after_create, before_create,
|
53
|
+
# then save the callback methods in @callbacks
|
54
54
|
def remember_callback(node)
|
55
55
|
if node.message.to_s =~ /^after_|^before_/
|
56
56
|
node.arguments.all.each do |argument|
|
@@ -60,21 +60,21 @@ module RailsBestPractices
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
-
|
63
|
+
# check a defn node to see if the method name exists in the @callbacks.
|
64
64
|
def callback_method?(node)
|
65
65
|
@callbacks.find { |callback| callback == node.method_name.to_s }
|
66
66
|
end
|
67
67
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
68
|
+
# check a def node to see if it contains a actionmailer deliver call.
|
69
|
+
#
|
70
|
+
# if the message of call node is deliver,
|
71
|
+
# and the receiver of the call node is with receiver node who exists in @callbacks,
|
72
|
+
# then the call node is actionmailer deliver call.
|
73
73
|
def deliver_mailer?(node)
|
74
74
|
node.grep_nodes(sexp_type: :call) do |child_node|
|
75
75
|
if child_node.message.to_s == 'deliver'
|
76
76
|
if child_node.receiver.sexp_type == :method_add_arg &&
|
77
|
-
|
77
|
+
mailers.include?(child_node.receiver[1].receiver.to_s)
|
78
78
|
return true
|
79
79
|
end
|
80
80
|
end
|
@@ -34,11 +34,12 @@ module RailsBestPractices
|
|
34
34
|
#
|
35
35
|
# then the call node can use query attribute instead.
|
36
36
|
add_callback :start_if, :start_unless, :start_elsif, :start_ifop, :start_if_mod, :start_unless_mod do |node|
|
37
|
-
all_conditions =
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
all_conditions =
|
38
|
+
if node.conditional_statement == node.conditional_statement.all_conditions
|
39
|
+
[node.conditional_statement]
|
40
|
+
else
|
41
|
+
node.conditional_statement.all_conditions
|
42
|
+
end
|
42
43
|
all_conditions.each do |condition_node|
|
43
44
|
next unless query_attribute_node = query_attribute_node(condition_node)
|
44
45
|
|
@@ -51,13 +52,13 @@ module RailsBestPractices
|
|
51
52
|
|
52
53
|
private
|
53
54
|
|
54
|
-
|
55
|
-
|
55
|
+
# recursively check conditional statement nodes to see if there is a call node that may be
|
56
|
+
# possible query attribute.
|
56
57
|
def query_attribute_node(conditional_statement_node)
|
57
58
|
case conditional_statement_node.sexp_type
|
58
59
|
when :and, :or
|
59
|
-
node =
|
60
|
-
|
60
|
+
node =
|
61
|
+
query_attribute_node(conditional_statement_node[1]) || query_attribute_node(conditional_statement_node[2])
|
61
62
|
node.file = conditional_statement_code.file
|
62
63
|
return node
|
63
64
|
when :not
|
@@ -71,17 +72,17 @@ module RailsBestPractices
|
|
71
72
|
nil
|
72
73
|
end
|
73
74
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
75
|
+
# check if the node may use query attribute instead.
|
76
|
+
#
|
77
|
+
# if the node contains two method calls, e.g. @user.login.nil?
|
78
|
+
#
|
79
|
+
# for the first call, the receiver should be one of the class names and
|
80
|
+
# the message should be one of the attribute name.
|
81
|
+
#
|
82
|
+
# for the second call, the message should be one of nil?, blank? or present? or
|
83
|
+
# it is compared with an empty string.
|
84
|
+
#
|
85
|
+
# the node that may use query attribute.
|
85
86
|
def possible_query_attribute?(node)
|
86
87
|
return false unless node.receiver.sexp_type == :call
|
87
88
|
|
@@ -92,7 +93,7 @@ module RailsBestPractices
|
|
92
93
|
(QUERY_METHODS.include?(node.message.to_s) || compare_with_empty_string?(node))
|
93
94
|
end
|
94
95
|
|
95
|
-
|
96
|
+
# check if the receiver is one of the models.
|
96
97
|
def is_model?(variable_node)
|
97
98
|
return false if variable_node.const?
|
98
99
|
|
@@ -100,18 +101,17 @@ module RailsBestPractices
|
|
100
101
|
models.include?(class_name)
|
101
102
|
end
|
102
103
|
|
103
|
-
|
104
|
-
|
104
|
+
# check if the receiver and message is one of the model's attribute.
|
105
|
+
# the receiver should match one of the class model name, and the message should match one of attribute name.
|
105
106
|
def model_attribute?(variable_node, message)
|
106
107
|
class_name = variable_node.to_s.sub(/^@/, '').classify
|
107
108
|
attribute_type = model_attributes.get_attribute_type(class_name, message)
|
108
109
|
attribute_type && !%w[integer float].include?(attribute_type)
|
109
110
|
end
|
110
111
|
|
111
|
-
|
112
|
+
# check if the node is with node type :binary, node message :== and node argument is empty string.
|
112
113
|
def compare_with_empty_string?(node)
|
113
|
-
node.sexp_type == :binary &&
|
114
|
-
['==', '!='].include?(node.message.to_s) &&
|
114
|
+
node.sexp_type == :binary && ['==', '!='].include?(node.message.to_s) &&
|
115
115
|
s(:string_literal, s(:string_content)) == node.argument
|
116
116
|
end
|
117
117
|
end
|
@@ -31,13 +31,14 @@ module RailsBestPractices
|
|
31
31
|
node.body.statements.each do |child_node|
|
32
32
|
next if child_node.grep_nodes_count(sexp_type: %i[fcall command], message: WITH_SAY_METHODS) > 0
|
33
33
|
|
34
|
-
receiver_node =
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
34
|
+
receiver_node =
|
35
|
+
if child_node.sexp_type == :method_add_block
|
36
|
+
child_node[1]
|
37
|
+
elsif child_node.sexp_type == :method_add_arg
|
38
|
+
child_node[1]
|
39
|
+
else
|
40
|
+
child_node
|
41
|
+
end
|
41
42
|
if receiver_node.sexp_type == :call
|
42
43
|
add_error('use say with time in migrations', node.file, child_node.line_number)
|
43
44
|
end
|
@@ -30,25 +30,27 @@ module RailsBestPractices
|
|
30
30
|
|
31
31
|
private
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
33
|
+
# check a if node to see
|
34
|
+
#
|
35
|
+
# if the conditional statement is compared with current_user or current_user.id,
|
36
|
+
# and there is a redirect_to method call in the block body,
|
37
|
+
# then it should be replaced by using scope access.
|
38
38
|
def current_user_redirect?(node)
|
39
|
-
all_conditions =
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
39
|
+
all_conditions =
|
40
|
+
if node.conditional_statement == node.conditional_statement.all_conditions
|
41
|
+
[node.conditional_statement]
|
42
|
+
else
|
43
|
+
node.conditional_statement.all_conditions
|
44
|
+
end
|
45
|
+
results =
|
46
|
+
all_conditions.map do |condition_node|
|
47
|
+
['==', '!='].include?(condition_node.message.to_s) &&
|
48
|
+
(current_user?(condition_node.argument) || current_user?(condition_node.receiver))
|
49
|
+
end
|
48
50
|
results.any? { |result| result == true } && node.body.grep_node(message: 'redirect_to')
|
49
51
|
end
|
50
52
|
|
51
|
-
|
53
|
+
# check a call node to see if it uses current_user, or current_user.id.
|
52
54
|
def current_user?(node)
|
53
55
|
node.to_s == 'current_user' || (node.receiver.to_s == 'current_user' && node.message.to_s == 'id')
|
54
56
|
end
|
@@ -18,7 +18,8 @@ module RailsBestPractices
|
|
18
18
|
# check command node to see if load 'deploy/assets'
|
19
19
|
add_callback :start_command do |node|
|
20
20
|
if Prepares.gems.gem_version('rails').to_i == 3
|
21
|
-
if !Prepares.gems.has_gem?('turbo-sprockets-rails3') && node.message.to_s == 'load' &&
|
21
|
+
if !Prepares.gems.has_gem?('turbo-sprockets-rails3') && node.message.to_s == 'load' &&
|
22
|
+
node.arguments.to_s == 'deploy/assets'
|
22
23
|
add_error 'speed up assets precompile with turbo-sprockets-rails3'
|
23
24
|
end
|
24
25
|
end
|
@@ -2,42 +2,41 @@
|
|
2
2
|
|
3
3
|
require File.expand_path('lib/rails_best_practices/version', __dir__)
|
4
4
|
|
5
|
-
Gem::Specification.new do |
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
s.post_install_message = <<~POST_INSTALL_MESSAGE
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'rails_best_practices'
|
7
|
+
spec.version = RailsBestPractices::VERSION
|
8
|
+
spec.platform = Gem::Platform::RUBY
|
9
|
+
spec.authors = ['Richard Huang']
|
10
|
+
spec.email = ['flyerhzm@gmail.com']
|
11
|
+
spec.homepage = 'http://rails-bestpractices.com'
|
12
|
+
spec.summary = 'a code metric tool for rails codes.'
|
13
|
+
spec.description = 'a code metric tool for rails codes, written in Ruby.'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.required_ruby_version = '>= 1.9.0'
|
17
|
+
spec.required_rubygems_version = '>= 1.3.6'
|
18
|
+
|
19
|
+
spec.add_dependency('activesupport')
|
20
|
+
spec.add_dependency('code_analyzer', '>= 0.5.2')
|
21
|
+
spec.add_dependency('erubis')
|
22
|
+
spec.add_dependency('i18n')
|
23
|
+
spec.add_dependency('json')
|
24
|
+
spec.add_dependency('require_all', '~> 3.0')
|
25
|
+
spec.add_dependency('ruby-progressbar')
|
26
|
+
|
27
|
+
spec.add_development_dependency('awesome_print')
|
28
|
+
spec.add_development_dependency('bundler')
|
29
|
+
spec.add_development_dependency('haml')
|
30
|
+
spec.add_development_dependency('rake')
|
31
|
+
spec.add_development_dependency('rspec')
|
32
|
+
spec.add_development_dependency('slim')
|
33
|
+
|
34
|
+
spec.files = `git ls-files`.split($/)
|
35
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
36
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
37
|
+
spec.require_paths = %w[lib assets]
|
38
|
+
|
39
|
+
spec.post_install_message = <<~POST_INSTALL_MESSAGE
|
41
40
|
#{'*' * 80}
|
42
41
|
|
43
42
|
rails_best_practices is a code metric tool to check the quality of rails codes.
|
@@ -5,8 +5,7 @@ require 'rails_best_practices/reviews/review'
|
|
5
5
|
module RailsBestPractices
|
6
6
|
module Plugins
|
7
7
|
module Reviews
|
8
|
-
class NotUseRailsRootReview < RailsBestPractices::Reviews::Review
|
9
|
-
end
|
8
|
+
class NotUseRailsRootReview < RailsBestPractices::Reviews::Review; end
|
10
9
|
end
|
11
10
|
end
|
12
11
|
end
|
@@ -5,39 +5,70 @@ require 'tmpdir'
|
|
5
5
|
|
6
6
|
module RailsBestPractices
|
7
7
|
describe Analyzer do
|
8
|
-
subject {
|
8
|
+
subject { described_class.new('.') }
|
9
9
|
|
10
10
|
describe '::new' do
|
11
|
-
it '
|
11
|
+
it 'expands a relative path to an absolute' do
|
12
12
|
expect(subject.path).to eq File.expand_path('.')
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
16
|
describe 'expand_dirs_to_files' do
|
17
|
-
it '
|
17
|
+
it 'expands all files in spec directory' do
|
18
18
|
dir = File.dirname(__FILE__)
|
19
19
|
expect(subject.expand_dirs_to_files(dir)).to be_include(dir + '/analyzer_spec.rb')
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
23
|
describe 'file_sort' do
|
24
|
-
it '
|
25
|
-
files = [
|
26
|
-
|
24
|
+
it 'gets models first, mailers, helpers and then others' do
|
25
|
+
files = [
|
26
|
+
'app/controllers/users_controller.rb',
|
27
|
+
'app/mailers/user_mailer.rb',
|
28
|
+
'app/helpers/users_helper.rb',
|
29
|
+
'app/models/user.rb',
|
30
|
+
'app/views/users/index.html.haml',
|
31
|
+
'app/views/users/show.html.slim',
|
32
|
+
'lib/user.rb'
|
33
|
+
]
|
34
|
+
expect(subject.file_sort(files)).to eq(
|
35
|
+
[
|
36
|
+
'app/models/user.rb',
|
37
|
+
'app/mailers/user_mailer.rb',
|
38
|
+
'app/helpers/users_helper.rb',
|
39
|
+
'app/controllers/users_controller.rb',
|
40
|
+
'app/views/users/index.html.haml',
|
41
|
+
'app/views/users/show.html.slim',
|
42
|
+
'lib/user.rb'
|
43
|
+
]
|
44
|
+
)
|
27
45
|
end
|
28
46
|
end
|
29
47
|
|
30
48
|
describe 'file_ignore' do
|
31
49
|
before do
|
32
|
-
@all = [
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
50
|
+
@all = [
|
51
|
+
'app/controllers/users_controller.rb',
|
52
|
+
'app/mailers/user_mailer.rb',
|
53
|
+
'app/models/user.rb',
|
54
|
+
'app/views/users/index.html.haml',
|
55
|
+
'app/views/users/show.html.slim',
|
56
|
+
'lib/user.rb'
|
57
|
+
]
|
58
|
+
@filtered = [
|
59
|
+
'app/controllers/users_controller.rb',
|
60
|
+
'app/mailers/user_mailer.rb',
|
61
|
+
'app/models/user.rb',
|
62
|
+
'app/views/users/index.html.haml',
|
63
|
+
'app/views/users/show.html.slim'
|
64
|
+
]
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'ignores lib' do
|
37
68
|
expect(subject.file_ignore(@all, 'lib/')).to eq(@filtered)
|
38
69
|
end
|
39
70
|
|
40
|
-
it '
|
71
|
+
it 'ignores regexp patterns' do
|
41
72
|
expect(subject.file_ignore(@all, /lib/)).to eq(@filtered)
|
42
73
|
end
|
43
74
|
end
|
@@ -88,7 +119,7 @@ module RailsBestPractices
|
|
88
119
|
end
|
89
120
|
|
90
121
|
describe 'output_terminal_errors' do
|
91
|
-
it '
|
122
|
+
it 'outputs errors in terminal' do
|
92
123
|
check1 = Reviews::LawOfDemeterReview.new
|
93
124
|
check2 = Reviews::UseQueryAttributeReview.new
|
94
125
|
runner = Core::Runner.new(reviews: [check1, check2])
|
@@ -102,12 +133,14 @@ module RailsBestPractices
|
|
102
133
|
subject.output_terminal_errors
|
103
134
|
result = $stdout.string
|
104
135
|
$stdout = $origin_stdout
|
105
|
-
expect(result).to eq(
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
136
|
+
expect(result).to eq(
|
137
|
+
[
|
138
|
+
"\e[31mapp/models/user.rb:10 - law of demeter\e[0m",
|
139
|
+
"\e[31mapp/models/post.rb:100 - use query attribute\e[0m",
|
140
|
+
"\e[32m\nPlease go to https://rails-bestpractices.com to see more useful Rails Best Practices.\e[0m",
|
141
|
+
"\e[31m\nFound 2 warnings.\e[0m"
|
142
|
+
].join("\n") + "\n"
|
143
|
+
)
|
111
144
|
end
|
112
145
|
end
|
113
146
|
|
@@ -115,9 +148,7 @@ module RailsBestPractices
|
|
115
148
|
let(:output_file) { 'rails_best_practices_output.json' }
|
116
149
|
|
117
150
|
subject do
|
118
|
-
described_class.new('.',
|
119
|
-
'format' => 'json',
|
120
|
-
'output-file' => output_file)
|
151
|
+
described_class.new('.', 'format' => 'json', 'output-file' => output_file)
|
121
152
|
end
|
122
153
|
|
123
154
|
let(:check1) { Reviews::LawOfDemeterReview.new }
|
@@ -142,54 +173,54 @@ module RailsBestPractices
|
|
142
173
|
end
|
143
174
|
|
144
175
|
describe 'parse_files' do
|
145
|
-
it '
|
146
|
-
Dir.mktmpdir
|
176
|
+
it 'does not filter out all files when the path contains "vendor"' do
|
177
|
+
Dir.mktmpdir do |random_dir|
|
147
178
|
Dir.mkdir(File.join(random_dir, 'vendor'))
|
148
179
|
Dir.mkdir(File.join(random_dir, 'vendor', 'my_project'))
|
149
180
|
File.open(File.join(random_dir, 'vendor', 'my_project', 'my_file.rb'), 'w') { |file| file << 'woot' }
|
150
|
-
analyzer =
|
181
|
+
analyzer = described_class.new(File.join(random_dir, 'vendor', 'my_project'))
|
151
182
|
expect(analyzer.parse_files).to be_include File.join(random_dir, 'vendor', 'my_project', 'my_file.rb')
|
152
|
-
|
183
|
+
end
|
153
184
|
end
|
154
185
|
|
155
|
-
it '
|
156
|
-
Dir.mktmpdir
|
186
|
+
it 'does not filter out all files when the path contains "spec"' do
|
187
|
+
Dir.mktmpdir do |random_dir|
|
157
188
|
Dir.mkdir(File.join(random_dir, 'spec'))
|
158
189
|
Dir.mkdir(File.join(random_dir, 'spec', 'my_project'))
|
159
190
|
File.open(File.join(random_dir, 'spec', 'my_project', 'my_file.rb'), 'w') { |file| file << 'woot' }
|
160
|
-
analyzer =
|
191
|
+
analyzer = described_class.new(File.join(random_dir, 'spec', 'my_project'))
|
161
192
|
expect(analyzer.parse_files).to be_include File.join(random_dir, 'spec', 'my_project', 'my_file.rb')
|
162
|
-
|
193
|
+
end
|
163
194
|
end
|
164
195
|
|
165
|
-
it '
|
166
|
-
Dir.mktmpdir
|
196
|
+
it 'does not filter out all files when the path contains "test"' do
|
197
|
+
Dir.mktmpdir do |random_dir|
|
167
198
|
Dir.mkdir(File.join(random_dir, 'test'))
|
168
199
|
Dir.mkdir(File.join(random_dir, 'test', 'my_project'))
|
169
200
|
File.open(File.join(random_dir, 'test', 'my_project', 'my_file.rb'), 'w') { |file| file << 'woot' }
|
170
|
-
analyzer =
|
201
|
+
analyzer = described_class.new(File.join(random_dir, 'test', 'my_project'))
|
171
202
|
expect(analyzer.parse_files).to be_include File.join(random_dir, 'test', 'my_project', 'my_file.rb')
|
172
|
-
|
203
|
+
end
|
173
204
|
end
|
174
205
|
|
175
|
-
it '
|
176
|
-
Dir.mktmpdir
|
206
|
+
it 'does not filter out all files when the path contains "features"' do
|
207
|
+
Dir.mktmpdir do |random_dir|
|
177
208
|
Dir.mkdir(File.join(random_dir, 'test'))
|
178
209
|
Dir.mkdir(File.join(random_dir, 'test', 'my_project'))
|
179
210
|
File.open(File.join(random_dir, 'test', 'my_project', 'my_file.rb'), 'w') { |file| file << 'woot' }
|
180
|
-
analyzer =
|
211
|
+
analyzer = described_class.new(File.join(random_dir, 'test', 'my_project'))
|
181
212
|
expect(analyzer.parse_files).to be_include File.join(random_dir, 'test', 'my_project', 'my_file.rb')
|
182
|
-
|
213
|
+
end
|
183
214
|
end
|
184
215
|
|
185
|
-
it '
|
186
|
-
Dir.mktmpdir
|
216
|
+
it 'does not filter out all files when the path contains "tmp"' do
|
217
|
+
Dir.mktmpdir do |random_dir|
|
187
218
|
Dir.mkdir(File.join(random_dir, 'tmp'))
|
188
219
|
Dir.mkdir(File.join(random_dir, 'tmp', 'my_project'))
|
189
220
|
File.open(File.join(random_dir, 'tmp', 'my_project', 'my_file.rb'), 'w') { |file| file << 'woot' }
|
190
|
-
analyzer =
|
221
|
+
analyzer = described_class.new(File.join(random_dir, 'tmp', 'my_project'))
|
191
222
|
expect(analyzer.parse_files).to be_include File.join(random_dir, 'tmp', 'my_project', 'my_file.rb')
|
192
|
-
|
223
|
+
end
|
193
224
|
end
|
194
225
|
end
|
195
226
|
end
|