rails_best_practices 1.10.1 → 1.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +1 -0
- data/README.md +11 -6
- data/assets/result.html.erb +76 -46
- data/install_supported_rubies.sh +3 -0
- data/lib/rails_best_practices.rb +2 -1
- data/lib/rails_best_practices/analyzer.rb +10 -8
- data/lib/rails_best_practices/core.rb +0 -4
- data/lib/rails_best_practices/core/check.rb +41 -117
- data/lib/rails_best_practices/core/error.rb +3 -9
- data/lib/rails_best_practices/core/runner.rb +20 -80
- data/lib/rails_best_practices/lexicals/long_line_check.rb +2 -1
- data/lib/rails_best_practices/lexicals/remove_tab_check.rb +1 -3
- data/lib/rails_best_practices/lexicals/remove_trailing_whitespace_check.rb +1 -3
- data/lib/rails_best_practices/prepares/config_prepare.rb +1 -1
- data/lib/rails_best_practices/prepares/controller_prepare.rb +7 -8
- data/lib/rails_best_practices/prepares/helper_prepare.rb +2 -2
- data/lib/rails_best_practices/prepares/mailer_prepare.rb +1 -1
- data/lib/rails_best_practices/prepares/model_prepare.rb +6 -7
- data/lib/rails_best_practices/prepares/route_prepare.rb +12 -13
- data/lib/rails_best_practices/prepares/schema_prepare.rb +2 -2
- data/lib/rails_best_practices/reviews/add_model_virtual_attribute_review.rb +19 -15
- data/lib/rails_best_practices/reviews/always_add_db_index_review.rb +10 -17
- data/lib/rails_best_practices/reviews/dry_bundler_in_capistrano_review.rb +2 -5
- data/lib/rails_best_practices/reviews/hash_syntax_review.rb +3 -30
- data/lib/rails_best_practices/reviews/isolate_seed_data_review.rb +7 -10
- data/lib/rails_best_practices/reviews/keep_finders_on_their_own_model_review.rb +5 -9
- data/lib/rails_best_practices/reviews/law_of_demeter_review.rb +10 -13
- data/lib/rails_best_practices/reviews/move_code_into_controller_review.rb +6 -9
- data/lib/rails_best_practices/reviews/move_code_into_helper_review.rb +2 -5
- data/lib/rails_best_practices/reviews/move_code_into_model_review.rb +7 -13
- data/lib/rails_best_practices/reviews/move_finder_to_named_scope_review.rb +3 -6
- data/lib/rails_best_practices/reviews/move_model_logic_into_model_review.rb +6 -9
- data/lib/rails_best_practices/reviews/needless_deep_nesting_review.rb +3 -6
- data/lib/rails_best_practices/reviews/not_use_default_route_review.rb +4 -7
- data/lib/rails_best_practices/reviews/not_use_time_ago_in_words_review.rb +2 -5
- data/lib/rails_best_practices/reviews/overuse_route_customizations_review.rb +7 -10
- data/lib/rails_best_practices/reviews/protect_mass_assignment_review.rb +2 -5
- data/lib/rails_best_practices/reviews/remove_empty_helpers_review.rb +2 -5
- data/lib/rails_best_practices/reviews/remove_unused_methods_in_controllers_review.rb +8 -6
- data/lib/rails_best_practices/reviews/remove_unused_methods_in_helpers_review.rb +1 -2
- data/lib/rails_best_practices/reviews/remove_unused_methods_in_models_review.rb +4 -5
- data/lib/rails_best_practices/reviews/replace_complex_creation_with_factory_method_review.rb +9 -12
- data/lib/rails_best_practices/reviews/replace_instance_variable_with_local_variable_review.rb +2 -13
- data/lib/rails_best_practices/reviews/restrict_auto_generated_routes_review.rb +18 -26
- data/lib/rails_best_practices/reviews/review.rb +6 -7
- data/lib/rails_best_practices/reviews/simplify_render_in_controllers_review.rb +2 -5
- data/lib/rails_best_practices/reviews/simplify_render_in_views_review.rb +2 -5
- data/lib/rails_best_practices/reviews/use_before_filter_review.rb +2 -5
- data/lib/rails_best_practices/reviews/use_model_association_review.rb +11 -14
- data/lib/rails_best_practices/reviews/use_multipart_alternative_as_content_type_of_email_review.rb +11 -8
- data/lib/rails_best_practices/reviews/use_observer_review.rb +8 -11
- data/lib/rails_best_practices/reviews/use_parentheses_in_method_def_review.rb +1 -1
- data/lib/rails_best_practices/reviews/use_query_attribute_review.rb +12 -18
- data/lib/rails_best_practices/reviews/use_say_with_time_in_migrations_review.rb +7 -10
- data/lib/rails_best_practices/reviews/use_scope_access_review.rb +4 -10
- data/lib/rails_best_practices/version.rb +1 -1
- data/rails_best_practices.gemspec +1 -1
- data/rails_best_practices.yml +5 -5
- data/spec/rails_best_practices/core/check_spec.rb +0 -67
- data/spec/rails_best_practices/prepares/controller_prepare_spec.rb +0 -1
- data/spec/rails_best_practices/prepares/model_prepare_spec.rb +0 -4
- data/spec/rails_best_practices/reviews/hash_syntax_review_spec.rb +3 -30
- data/spec/rails_best_practices/reviews/remove_unused_methods_in_controllers_review_spec.rb +22 -0
- data/spec/rails_best_practices/reviews/remove_unused_methods_in_models_review_spec.rb +19 -0
- data/spec/rails_best_practices/reviews/use_multipart_alternative_as_content_type_of_email_review_spec.rb +2 -2
- data/spec/spec_helper.rb +0 -4
- metadata +28 -41
- data/Gemfile.lock +0 -71
- data/lib/rails_best_practices/core/checking_visitor.rb +0 -80
- data/lib/rails_best_practices/core/nil.rb +0 -37
- data/lib/rails_best_practices/core_ext/enumerable.rb +0 -9
- data/lib/rails_best_practices/core_ext/sexp.rb +0 -840
- data/spec/rails_best_practices/core/checking_visitor_spec.rb +0 -79
- data/spec/rails_best_practices/core/nil_spec.rb +0 -37
- data/spec/rails_best_practices/core_ext/enumerable_spec.rb +0 -7
- data/spec/rails_best_practices/core_ext/sexp_spec.rb +0 -613
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -22,6 +22,11 @@ following template engines:
|
|
22
22
|
|
23
23
|
rails_best_practices works well only in ruby 1.9.2 and ruby 1.9.3 so far.
|
24
24
|
|
25
|
+
## External Introduction
|
26
|
+
|
27
|
+
<http://ruby5.envylabs.com/episodes/257-episode-253-march-9th-2012/stories/2253-rails_best_practices>
|
28
|
+
<http://railscasts.com/episodes/252-metrics-metrics-metrics>
|
29
|
+
|
25
30
|
## Usage
|
26
31
|
|
27
32
|
At the root directory of rails app
|
@@ -111,11 +116,11 @@ Now you can customize this configuration file, the default configuration is as f
|
|
111
116
|
AddModelVirtualAttributeCheck: { }
|
112
117
|
AlwaysAddDbIndexCheck: { }
|
113
118
|
DryBundlerInCapistranoCheck: { }
|
114
|
-
HashSyntaxCheck: {
|
119
|
+
#HashSyntaxCheck: { }
|
115
120
|
IsolateSeedDataCheck: { }
|
116
121
|
KeepFindersOnTheirOwnModelCheck: { }
|
117
122
|
LawOfDemeterCheck: { }
|
118
|
-
LongLineCheck: { max_line_length: 80 }
|
123
|
+
#LongLineCheck: { max_line_length: 80 }
|
119
124
|
MoveCodeIntoControllerCheck: { }
|
120
125
|
MoveCodeIntoHelperCheck: { array_count: 3 }
|
121
126
|
MoveCodeIntoModelCheck: { use_count: 2 }
|
@@ -127,7 +132,7 @@ Now you can customize this configuration file, the default configuration is as f
|
|
127
132
|
OveruseRouteCustomizationsCheck: { customize_count: 3 }
|
128
133
|
ProtectMassAssignmentCheck: {}
|
129
134
|
RemoveEmptyHelpersCheck: {}
|
130
|
-
RemoveTabCheck: {}
|
135
|
+
#RemoveTabCheck: {}
|
131
136
|
RemoveTrailingWhitespaceCheck: { }
|
132
137
|
RemoveUnusedMethodsInControllersCheck: { except_methods: [] }
|
133
138
|
RemoveUnusedMethodsInHelpersCheck: { except_methods: [] }
|
@@ -137,11 +142,11 @@ Now you can customize this configuration file, the default configuration is as f
|
|
137
142
|
RestrictAutoGeneratedRoutesCheck: { }
|
138
143
|
SimplifyRenderInControllersCheck: {}
|
139
144
|
SimplifyRenderInViewsCheck: {}
|
140
|
-
UseBeforeFilterCheck: { customize_count: 2 }
|
145
|
+
#UseBeforeFilterCheck: { customize_count: 2 }
|
141
146
|
UseModelAssociationCheck: { }
|
142
147
|
UseMultipartAlternativeAsContentTypeOfEmailCheck: {}
|
143
148
|
UseObserverCheck: { }
|
144
|
-
UseParenthesesInMethodDefCheck: {}
|
149
|
+
#UseParenthesesInMethodDefCheck: {}
|
145
150
|
UseQueryAttributeCheck: { }
|
146
151
|
UseSayWithTimeInMigrationsCheck: { }
|
147
152
|
UseScopeAccessCheck: { }
|
@@ -237,4 +242,4 @@ Send us email: <team@railsbp.com>
|
|
237
242
|
Copyright © 2009 - 2012 Richard Huang (flyerhzm@gmail.com), released under the MIT license
|
238
243
|
|
239
244
|
|
240
|
-
[1]:https://github.com/railsbp/rails_best_practices/wiki/How-to-write-your-own-check-list
|
245
|
+
[1]: https://github.com/railsbp/rails_best_practices/wiki/How-to-write-your-own-check-list
|
data/assets/result.html.erb
CHANGED
@@ -22,18 +22,18 @@
|
|
22
22
|
margin: 10px 0;
|
23
23
|
font-size: 14px;
|
24
24
|
}
|
25
|
-
table th, table td {
|
25
|
+
table.result th, table.result td {
|
26
26
|
padding: 4px;
|
27
27
|
border: 1px solid #D0D0D0;
|
28
28
|
}
|
29
|
-
table th {
|
29
|
+
table.result th {
|
30
30
|
background-color: #DFC;
|
31
31
|
color: #337022;
|
32
32
|
}
|
33
|
-
table td.filename {
|
33
|
+
table.result td.filename {
|
34
34
|
color: #ED1556;
|
35
35
|
}
|
36
|
-
table tr:hover {
|
36
|
+
table.result tr:hover {
|
37
37
|
background-color: #FFFFC0;
|
38
38
|
}
|
39
39
|
ul {
|
@@ -48,6 +48,14 @@
|
|
48
48
|
float: left;
|
49
49
|
}
|
50
50
|
</style>
|
51
|
+
<%
|
52
|
+
def columnize(arr, col_count)
|
53
|
+
row_count = arr.size / col_count
|
54
|
+
row_count += 1 if arr.size % col_count > 0
|
55
|
+
cols = arr.each_slice(row_count).to_a
|
56
|
+
cols[0].zip(*cols[1..-1]).map(&:compact)
|
57
|
+
end
|
58
|
+
%>
|
51
59
|
</head>
|
52
60
|
<body>
|
53
61
|
<h1>rails_best_practices output</h1>
|
@@ -63,59 +71,73 @@
|
|
63
71
|
Found <%= @errors.size %> warnings.
|
64
72
|
<% end %>
|
65
73
|
</p>
|
66
|
-
<ul>
|
67
|
-
<% @error_types.each do |error_type| %>
|
68
|
-
<li>
|
69
|
-
<input type="checkbox" id="<%= error_type.split(':').last %>" value="<%= error_type.split(':').last %>" />
|
70
|
-
<label for="<%= error_type.split(':').last%>"><%= error_type.split(':').last%></label>
|
71
|
-
</li>
|
72
|
-
<% end %>
|
73
|
-
</ul>
|
74
74
|
<table>
|
75
|
+
<% columnize(@error_types, 3).each do |row| %>
|
76
|
+
<tr>
|
77
|
+
<% row.map { |error_type| error_type.split(':').last }.each do |error_type| %>
|
78
|
+
<td>
|
79
|
+
<input type="checkbox" class="error-type" id="<%= error_type %>" value="<%= error_type %>"
|
80
|
+
/> <label for="<%= error_type %>"><%= error_type.sub(/(Check|Review)$/, '').gsub(/([a-z\d])([A-Z])/,'\1 \2') %></label>
|
81
|
+
</td>
|
82
|
+
<% end %>
|
83
|
+
</tr>
|
84
|
+
<% end %>
|
75
85
|
<tr>
|
76
|
-
<
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
<th>Hg Commit</th>
|
81
|
-
<th>Hg Username</th>
|
82
|
-
<% elsif @git %>
|
83
|
-
<th>Git Commit</th>
|
84
|
-
<th>Git Username</th>
|
85
|
-
<% end %>
|
86
|
+
<td colspan="3">
|
87
|
+
<button id="show-all">Check all</button>
|
88
|
+
<button id="show-none">Uncheck all</button>
|
89
|
+
</td>
|
86
90
|
</tr>
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
<% elsif @mvim %>
|
95
|
-
<a href='mvim://open/?url=file://<%= File.expand_path(error.filename) %>&line=<%= error.line_number %>'><%= error.short_filename %></a>
|
96
|
-
<% else %>
|
97
|
-
<%= error.short_filename %>
|
98
|
-
<% end %>
|
99
|
-
</td>
|
100
|
-
<td class='line'><%= error.line_number %></td>
|
101
|
-
<td class='message'>
|
102
|
-
<a href='<%= error.url %>' target='_blank'><%= error.message %></a>
|
103
|
-
</td>
|
91
|
+
</table>
|
92
|
+
<table class="result">
|
93
|
+
<thead>
|
94
|
+
<tr>
|
95
|
+
<th>Filename</th>
|
96
|
+
<th>Line Number</th>
|
97
|
+
<th>Warning Message</th>
|
104
98
|
<% if @hg %>
|
105
|
-
<
|
106
|
-
<
|
99
|
+
<th>Hg Commit</th>
|
100
|
+
<th>Hg Username</th>
|
107
101
|
<% elsif @git %>
|
108
|
-
<
|
109
|
-
<
|
102
|
+
<th>Git Commit</th>
|
103
|
+
<th>Git Username</th>
|
110
104
|
<% end %>
|
111
105
|
</tr>
|
112
|
-
|
106
|
+
</thead>
|
107
|
+
<tbody>
|
108
|
+
<% @errors.each do |error| %>
|
109
|
+
<tr class="<%= error.type.split(':').last %>">
|
110
|
+
<td class='filename'>
|
111
|
+
<% if @github %>
|
112
|
+
<a href='https://github.com/<%= @github_name %>/blob/<%= @last_commit_id %>/<%= error.short_filename %>#L<%= error.first_line_number %>' target='_blank'><%= error.short_filename %></a>
|
113
|
+
<% elsif @textmate %>
|
114
|
+
<a href='txmt://open/?url=file://<%= File.expand_path(error.filename) %>&line=<%= error.line_number %>'><%= error.short_filename %></a>
|
115
|
+
<% elsif @mvim %>
|
116
|
+
<a href='mvim://open/?url=file://<%= File.expand_path(error.filename) %>&line=<%= error.line_number %>'><%= error.short_filename %></a>
|
117
|
+
<% else %>
|
118
|
+
<%= error.short_filename %>
|
119
|
+
<% end %>
|
120
|
+
</td>
|
121
|
+
<td class='line'><%= error.line_number %></td>
|
122
|
+
<td class='message'>
|
123
|
+
<a href='<%= error.url %>' target='_blank'><%= error.message %></a>
|
124
|
+
</td>
|
125
|
+
<% if @hg %>
|
126
|
+
<td class='hg_commit'><%= error.hg_commit %></td>
|
127
|
+
<td class='hg_usename'><%= error.hg_username %></td>
|
128
|
+
<% elsif @git %>
|
129
|
+
<td class='git_commit'><%= error.git_commit %></td>
|
130
|
+
<td class='git_usename'><%= error.git_username %></td>
|
131
|
+
<% end %>
|
132
|
+
</tr>
|
133
|
+
<% end %>
|
134
|
+
</tbody>
|
113
135
|
</table>
|
114
|
-
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.
|
136
|
+
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
|
115
137
|
<script type="text/javascript">
|
116
138
|
$(function() {
|
117
139
|
$('ul li').show();
|
118
|
-
$('input[type=checkbox]').prop('checked', true).click(function() {
|
140
|
+
$('input.error-type[type=checkbox]').prop('checked', true).click(function() {
|
119
141
|
if ($(this).attr('checked')) {
|
120
142
|
$(this).prop('checked', true);
|
121
143
|
$('.'+$(this).val()).show();
|
@@ -124,6 +146,14 @@
|
|
124
146
|
$('.'+$(this).val()).hide();
|
125
147
|
}
|
126
148
|
});
|
149
|
+
$('#show-all').click(function() {
|
150
|
+
$('input.error-type[type=checkbox]').prop('checked', true);
|
151
|
+
$('table.result tbody tr').show();
|
152
|
+
});
|
153
|
+
$('#show-none').click(function() {
|
154
|
+
$('input.error-type[type=checkbox]').prop('checked', false);
|
155
|
+
$('table.result tbody tr').hide();
|
156
|
+
});
|
127
157
|
});
|
128
158
|
</script>
|
129
159
|
</body>
|
data/install_supported_rubies.sh
CHANGED
data/lib/rails_best_practices.rb
CHANGED
@@ -8,7 +8,7 @@
|
|
8
8
|
# "Software"), to deal in the Software without restriction, including
|
9
9
|
# without limitation the rights to use, copy, modify, merge, publish,
|
10
10
|
# distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
-
# permit persons to whom the Software is furnished to do so,
|
11
|
+
# permit persons to whom the Software is furnished to do so, receiver to
|
12
12
|
# the following conditions:
|
13
13
|
#
|
14
14
|
# The above copyright notice and this permission notice shall be
|
@@ -22,6 +22,7 @@
|
|
22
22
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
23
23
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
24
24
|
#++
|
25
|
+
require 'code_analyzer'
|
25
26
|
require 'rails_best_practices/lexicals'
|
26
27
|
require 'rails_best_practices/prepares'
|
27
28
|
require 'rails_best_practices/reviews'
|
@@ -53,8 +53,6 @@ module RailsBestPractices
|
|
53
53
|
|
54
54
|
Core::Runner.base_path = @path
|
55
55
|
@runner = Core::Runner.new
|
56
|
-
@runner.debug = true if @options["debug"]
|
57
|
-
@runner.color = !@options["without-color"]
|
58
56
|
|
59
57
|
analyze_source_codes
|
60
58
|
analyze_vcs
|
@@ -79,7 +77,15 @@ module RailsBestPractices
|
|
79
77
|
# @param [String] process the process name, lexical, prepare or review.
|
80
78
|
def process(process)
|
81
79
|
parse_files.each do |file|
|
82
|
-
|
80
|
+
begin
|
81
|
+
puts file if @options["debug"]
|
82
|
+
@runner.send(process, file, File.read(file))
|
83
|
+
rescue
|
84
|
+
if @options["debug"]
|
85
|
+
warning = "#{file} looks like it's not a valid Ruby file. Skipping..."
|
86
|
+
plain_output(warning, 'red')
|
87
|
+
end
|
88
|
+
end
|
83
89
|
@bar.inc if display_bar?
|
84
90
|
end
|
85
91
|
@runner.send("after_#{process}")
|
@@ -116,7 +122,7 @@ module RailsBestPractices
|
|
116
122
|
# @param [Array] dirs what directories to expand
|
117
123
|
# @return [Array] all files expanded
|
118
124
|
def expand_dirs_to_files(*dirs)
|
119
|
-
extensions = ['rb', 'erb', 'rake', 'rhtml', 'haml', 'slim', 'builder', 'rxml']
|
125
|
+
extensions = ['rb', 'erb', 'rake', 'rhtml', 'haml', 'slim', 'builder', 'rxml', 'rabl']
|
120
126
|
|
121
127
|
dirs.flatten.map { |entry|
|
122
128
|
next unless File.exist? entry
|
@@ -140,10 +146,6 @@ module RailsBestPractices
|
|
140
146
|
mailers = files.find_all { |file| file =~ Core::Check::MAILER_FILES }
|
141
147
|
helpers = files.find_all { |file| file =~ Core::Check::HELPER_FILES }
|
142
148
|
others = files.find_all { |file| file !~ Core::Check::MAILER_FILES && file !~ Core::Check::MODEL_FILES && file !~ Core::Check::HELPER_FILES }
|
143
|
-
models.sort
|
144
|
-
mailers.sort
|
145
|
-
helpers.sort
|
146
|
-
others.sort
|
147
149
|
return models + mailers + helpers + others
|
148
150
|
end
|
149
151
|
|
@@ -1,9 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
require 'rails_best_practices/core/check'
|
3
3
|
require 'rails_best_practices/core/runner'
|
4
|
-
require 'rails_best_practices/core/checking_visitor'
|
5
4
|
require 'rails_best_practices/core/error'
|
6
|
-
require 'rails_best_practices/core/nil'
|
7
5
|
require 'rails_best_practices/core/klasses'
|
8
6
|
require 'rails_best_practices/core/modules'
|
9
7
|
require 'rails_best_practices/core/models'
|
@@ -16,6 +14,4 @@ require 'rails_best_practices/core/helpers'
|
|
16
14
|
require 'rails_best_practices/core/routes'
|
17
15
|
require 'rails_best_practices/core/configs'
|
18
16
|
|
19
|
-
require 'rails_best_practices/core_ext/sexp'
|
20
|
-
require 'rails_best_practices/core_ext/enumerable'
|
21
17
|
require 'rails_best_practices/core_ext/erubis'
|
@@ -2,78 +2,42 @@
|
|
2
2
|
module RailsBestPractices
|
3
3
|
module Core
|
4
4
|
# A Check class that takes charge of checking the sexp.
|
5
|
-
class Check
|
5
|
+
class Check < CodeAnalyzer::Checker
|
6
6
|
ALL_FILES = /.*/
|
7
|
-
CONTROLLER_FILES = /(controllers|cells)\/.*\.rb$/
|
7
|
+
CONTROLLER_FILES = /app\/(controllers|cells)\/.*\.rb$/
|
8
8
|
MIGRATION_FILES = /db\/migrate\/.*\.rb$/
|
9
|
-
MODEL_FILES = /models\/.*\.rb$/
|
10
|
-
MAILER_FILES = /models\/.*mailer\.rb$|mailers
|
11
|
-
VIEW_FILES = /(views|cells)\/.*\.(erb|haml|slim|builder|rxml)$/
|
12
|
-
PARTIAL_VIEW_FILES = /(views|cells)\/.*\/_.*\.(erb|haml|slim|builder|rxml)$/
|
9
|
+
MODEL_FILES = /app\/models\/.*\.rb$/
|
10
|
+
MAILER_FILES = /app\/models\/.*mailer\.rb$|app\/mailers\/.*\.rb/
|
11
|
+
VIEW_FILES = /app\/(views|cells)\/.*\.(erb|haml|slim|builder|rxml)$/
|
12
|
+
PARTIAL_VIEW_FILES = /app\/(views|cells)\/.*\/_.*\.(erb|haml|slim|builder|rxml)$/
|
13
13
|
ROUTE_FILES = /config\/routes.*\.rb/
|
14
14
|
SCHEMA_FILE = /db\/schema\.rb/
|
15
|
-
HELPER_FILES = /helpers\/.*\.rb$/
|
15
|
+
HELPER_FILES = /app\/helpers\/.*\.rb$/
|
16
16
|
DEPLOY_FILES = /config\/deploy.*\.rb/
|
17
17
|
CONFIG_FILES = /config\/(application|environment|environments\/.*)\.rb/
|
18
18
|
|
19
|
+
SKIP_FILES = /db\/schema.rb/
|
20
|
+
|
19
21
|
def initialize(options={})
|
20
22
|
options.each do |key, value|
|
21
23
|
instance_variable_set("@#{key}", value)
|
22
24
|
end
|
23
25
|
end
|
24
26
|
|
25
|
-
# interesting nodes that the check will parse.
|
26
|
-
def interesting_nodes
|
27
|
-
self.class.interesting_nodes
|
28
|
-
end
|
29
|
-
|
30
|
-
# interesting files that the check will parse.
|
31
|
-
def interesting_files
|
32
|
-
self.class.interesting_files
|
33
|
-
end
|
34
|
-
|
35
27
|
# check if the check will need to parse the node file.
|
36
28
|
#
|
37
29
|
# @param [String] the file name of node.
|
38
30
|
# @return [Boolean] true if the check will need to parse the file.
|
39
31
|
def parse_file?(node_file)
|
40
|
-
interesting_files.any?
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
# start_def
|
47
|
-
#
|
48
|
-
# @param [Sexp] node
|
49
|
-
def node_start(node)
|
50
|
-
@node = node
|
51
|
-
if self.class.debug?
|
52
|
-
ap node
|
53
|
-
end
|
54
|
-
Array(self.class.callbacks["start_#{node.sexp_type}"]).each do |callback|
|
55
|
-
self.instance_exec node, &callback
|
56
|
-
end
|
57
|
-
self.send("start_#{node.sexp_type}", node)
|
58
|
-
end
|
59
|
-
|
60
|
-
# delegate to end_### according to the sexp_type, like
|
61
|
-
#
|
62
|
-
# end_call
|
63
|
-
# end_def
|
64
|
-
#
|
65
|
-
# @param [Sexp] node
|
66
|
-
def node_end(node)
|
67
|
-
@node = node
|
68
|
-
self.send("end_#{node.sexp_type}", node)
|
69
|
-
Array(self.class.callbacks["end_#{node.sexp_type}"]).each do |callback|
|
70
|
-
self.instance_exec node, &callback
|
32
|
+
interesting_files.any? do |pattern|
|
33
|
+
if pattern == ALL_FILES
|
34
|
+
node_file =~ pattern && node_file !~ SKIP_FILES
|
35
|
+
else
|
36
|
+
node_file =~ pattern
|
37
|
+
end
|
71
38
|
end
|
72
39
|
end
|
73
40
|
|
74
|
-
def after_prepare; end
|
75
|
-
def after_review; end
|
76
|
-
|
77
41
|
# add error if source code violates rails best practice.
|
78
42
|
#
|
79
43
|
# @param [String] message, is the string message for violation of the rails best practice
|
@@ -98,7 +62,7 @@ module RailsBestPractices
|
|
98
62
|
#
|
99
63
|
# @return [String] the url of rails best practice
|
100
64
|
def url
|
101
|
-
|
65
|
+
self.class.url
|
102
66
|
end
|
103
67
|
|
104
68
|
# method_missing to catch all start and end process for each node type, like
|
@@ -120,30 +84,8 @@ module RailsBestPractices
|
|
120
84
|
end
|
121
85
|
|
122
86
|
class <<self
|
123
|
-
def
|
124
|
-
@
|
125
|
-
@interesting_nodes += nodes
|
126
|
-
@interesting_nodes.uniq
|
127
|
-
end
|
128
|
-
|
129
|
-
def interesting_files(*file_patterns)
|
130
|
-
@interesting_files ||= []
|
131
|
-
@interesting_files += file_patterns
|
132
|
-
@interesting_files.uniq
|
133
|
-
end
|
134
|
-
|
135
|
-
# callbacks for start_xxx and end_xxx.
|
136
|
-
def callbacks
|
137
|
-
@callbacks ||= {}
|
138
|
-
end
|
139
|
-
|
140
|
-
# add a callback.
|
141
|
-
#
|
142
|
-
# @param [String] name, callback name, can be start_xxx or end_xxx
|
143
|
-
# @param [Proc] block, be executed when callbacks are called
|
144
|
-
def add_callback(name, &block)
|
145
|
-
callbacks[name] ||= []
|
146
|
-
callbacks[name] << block
|
87
|
+
def url(url=nil)
|
88
|
+
url ? @url = url : @url
|
147
89
|
end
|
148
90
|
|
149
91
|
def debug?
|
@@ -162,23 +104,23 @@ module RailsBestPractices
|
|
162
104
|
interesting_nodes :module, :class
|
163
105
|
|
164
106
|
# remember module name
|
165
|
-
add_callback
|
107
|
+
add_callback :start_module do |node|
|
166
108
|
classable_modules << node.module_name.to_s
|
167
109
|
end
|
168
110
|
|
169
111
|
# end of the module.
|
170
|
-
add_callback
|
112
|
+
add_callback :end_module do |node|
|
171
113
|
classable_modules.pop
|
172
114
|
end
|
173
115
|
|
174
116
|
# remember the class anem
|
175
|
-
add_callback
|
117
|
+
add_callback :start_class do |node|
|
176
118
|
@klass = Core::Klass.new(node.class_name.to_s, node.base_class.to_s, classable_modules)
|
177
119
|
end
|
178
120
|
|
179
121
|
# end of the class
|
180
|
-
add_callback
|
181
|
-
|
122
|
+
add_callback :end_class do |node|
|
123
|
+
#@klass = nil
|
182
124
|
end
|
183
125
|
end
|
184
126
|
end
|
@@ -206,12 +148,12 @@ module RailsBestPractices
|
|
206
148
|
interesting_nodes :module
|
207
149
|
|
208
150
|
# remember module name
|
209
|
-
add_callback
|
151
|
+
add_callback :start_module do |node|
|
210
152
|
moduleable_modules << node.module_name.to_s
|
211
153
|
end
|
212
154
|
|
213
155
|
# end of module
|
214
|
-
add_callback
|
156
|
+
add_callback :end_module do |node|
|
215
157
|
moduleable_modules.pop
|
216
158
|
end
|
217
159
|
end
|
@@ -228,24 +170,6 @@ module RailsBestPractices
|
|
228
170
|
end
|
229
171
|
end
|
230
172
|
|
231
|
-
# Helper to add callback after all files reviewed.
|
232
|
-
module Afterable
|
233
|
-
def self.included(base)
|
234
|
-
base.class_eval do
|
235
|
-
interesting_nodes :class
|
236
|
-
interesting_files /rails_best_practices\.after_(prepare|review)/
|
237
|
-
|
238
|
-
add_callback "end_class" do |node|
|
239
|
-
if "RailsBestPractices::AfterPrepare" == node.class_name.to_s
|
240
|
-
after_prepare
|
241
|
-
elsif "RailsBestPractices::AfterReview" == node.class_name.to_s
|
242
|
-
after_review
|
243
|
-
end
|
244
|
-
end
|
245
|
-
end
|
246
|
-
end
|
247
|
-
end
|
248
|
-
|
249
173
|
# Helper to add callbacks to mark the methods are used.
|
250
174
|
module Callable
|
251
175
|
def self.included(base)
|
@@ -253,22 +177,22 @@ module RailsBestPractices
|
|
253
177
|
interesting_nodes :call, :fcall, :var_ref, :vcall, :command_call, :command, :alias, :bare_assoc_hash, :method_add_arg
|
254
178
|
|
255
179
|
# remembe the message of call node.
|
256
|
-
add_callback
|
180
|
+
add_callback :start_call do |node|
|
257
181
|
mark_used(node.message)
|
258
182
|
end
|
259
183
|
|
260
184
|
# remembe the message of fcall node.
|
261
|
-
add_callback
|
185
|
+
add_callback :start_fcall do |node|
|
262
186
|
mark_used(node.message)
|
263
187
|
end
|
264
188
|
|
265
189
|
# remembe name of var_ref node.
|
266
|
-
add_callback
|
190
|
+
add_callback :start_var_ref do |node|
|
267
191
|
mark_used(node)
|
268
192
|
end
|
269
193
|
|
270
194
|
# remembe name of vcall node.
|
271
|
-
add_callback
|
195
|
+
add_callback :start_vcall do |node|
|
272
196
|
mark_used(node)
|
273
197
|
end
|
274
198
|
|
@@ -279,7 +203,7 @@ module RailsBestPractices
|
|
279
203
|
|
280
204
|
# remember the message of command node.
|
281
205
|
# remember the argument of alias_method and alias_method_chain as well.
|
282
|
-
add_callback
|
206
|
+
add_callback :start_command do |node|
|
283
207
|
case node.message.to_s
|
284
208
|
when *skip_command_callback_nodes
|
285
209
|
# nothing
|
@@ -300,12 +224,12 @@ module RailsBestPractices
|
|
300
224
|
end
|
301
225
|
|
302
226
|
# remembe the message of command call node.
|
303
|
-
add_callback
|
227
|
+
add_callback :start_command_call do |node|
|
304
228
|
mark_used(node.message)
|
305
229
|
end
|
306
230
|
|
307
231
|
# remember the old method of alias node.
|
308
|
-
add_callback
|
232
|
+
add_callback :start_alias do |node|
|
309
233
|
mark_used(node.old_method)
|
310
234
|
end
|
311
235
|
|
@@ -314,14 +238,14 @@ module RailsBestPractices
|
|
314
238
|
# def to_xml(options = {})
|
315
239
|
# super options.merge(exclude: :visible, methods: [:is_discussion_conversation])
|
316
240
|
# end
|
317
|
-
add_callback
|
241
|
+
add_callback :start_bare_assoc_hash do |node|
|
318
242
|
if node.hash_keys.include? "methods"
|
319
243
|
mark_used(node.hash_value("methods"))
|
320
244
|
end
|
321
245
|
end
|
322
246
|
|
323
247
|
# remember the first argument for try and send method.
|
324
|
-
add_callback
|
248
|
+
add_callback :start_method_add_arg do |node|
|
325
249
|
case node.message.to_s
|
326
250
|
when "try"
|
327
251
|
mark_used(node.arguments.all.first)
|
@@ -368,21 +292,21 @@ module RailsBestPractices
|
|
368
292
|
interesting_files CONTROLLER_FILES
|
369
293
|
|
370
294
|
# check if the controller is inherit from InheritedResources::Base.
|
371
|
-
add_callback
|
295
|
+
add_callback :start_class do |node|
|
372
296
|
if "InheritedResources::Base" == current_extend_class_name
|
373
297
|
@inherited_resources = true
|
374
298
|
end
|
375
299
|
end
|
376
300
|
|
377
301
|
# check if there is a DSL call inherit_resources.
|
378
|
-
add_callback
|
302
|
+
add_callback :start_var_ref do |node|
|
379
303
|
if "inherit_resources" == node.to_s
|
380
304
|
@inherited_resources = true
|
381
305
|
end
|
382
306
|
end
|
383
307
|
|
384
308
|
# check if there is a DSL call inherit_resources.
|
385
|
-
add_callback
|
309
|
+
add_callback :start_vcall do |node|
|
386
310
|
if "inherit_resources" == node.to_s
|
387
311
|
@inherited_resources = true
|
388
312
|
end
|
@@ -424,26 +348,26 @@ module RailsBestPractices
|
|
424
348
|
interesting_nodes :var_ref, :vcall, :class, :module
|
425
349
|
|
426
350
|
# remember the current access control for methods.
|
427
|
-
add_callback
|
351
|
+
add_callback :start_var_ref do |node|
|
428
352
|
if %w(public protected private).include? node.to_s
|
429
353
|
@access_control = node.to_s
|
430
354
|
end
|
431
355
|
end
|
432
356
|
|
433
357
|
# remember the current access control for methods.
|
434
|
-
add_callback
|
358
|
+
add_callback :start_vcall do |node|
|
435
359
|
if %w(public protected private).include? node.to_s
|
436
360
|
@access_control = node.to_s
|
437
361
|
end
|
438
362
|
end
|
439
363
|
|
440
364
|
# set access control to "public" by default.
|
441
|
-
add_callback
|
365
|
+
add_callback :start_class do |node|
|
442
366
|
@access_control = "public"
|
443
367
|
end
|
444
368
|
|
445
369
|
# set access control to "public" by default.
|
446
|
-
add_callback
|
370
|
+
add_callback :start_module do |node|
|
447
371
|
@access_control = "public"
|
448
372
|
end
|
449
373
|
end
|