Class: RailsBestPractices::Analyzer
- Inherits:
-
Object
- Object
- RailsBestPractices::Analyzer
- Defined in:
- lib/rails_best_practices/analyzer.rb
Overview
RailsBestPractices Analyzer helps you to analyze your rails code, according to best practices on rails-bestpractices. if it finds any violatioins to best practices, it will give you some readable suggestions.
The analysis process is partitioned into two parts,
-
prepare process, it checks only model and mailer files, do some preparations, such as remember model names and associations.
-
review process, it checks all files, according to configuration, it really check if codes violate the best practices, if so, remember the violations.
After analyzing, output the violations.
Constant Summary collapse
- DEFAULT_CONFIG =
File.join(File.dirname(__FILE__), "..", "..", "rails_best_practices.yml")
Instance Attribute Summary collapse
-
#runner ⇒ Object
Returns the value of attribute runner.
Instance Method Summary collapse
-
#analyze ⇒ Object
Analyze rails codes.
- #display_bar? ⇒ Boolean
-
#error_types ⇒ Object
unique error types.
-
#expand_dirs_to_files(*dirs) ⇒ Array
expand all files with extenstion rb, erb, haml, slim, builder and rxml under the dirs.
-
#file_accept(files, patterns) ⇒ Object
accept specific files.
-
#file_ignore(files, pattern) ⇒ Array
ignore specific files.
-
#file_sort(files) ⇒ Array
sort files, models first, mailers, helpers, and then sort other files by characters.
-
#generate ⇒ Object
generate configuration yaml file.
-
#initialize(path, options = {}) ⇒ Analyzer
constructor
initialize.
-
#load_git_info ⇒ Object
load git commit and git username info.
-
#load_hg_info ⇒ Object
load hg commit and hg username info.
-
#output ⇒ Object
Output the analyze result.
-
#output_html_errors ⇒ Object
output errors with html format.
-
#output_terminal_errors ⇒ Object
output errors on terminal.
-
#parse_files ⇒ Array
get all files for parsing.
-
#plain_output(message, color) ⇒ Object
plain output with color.
-
#process(process) ⇒ Object
process lexical, prepare or reivew.
Constructor Details
#initialize(path, options = {}) ⇒ Analyzer
initialize
26 27 28 29 |
# File 'lib/rails_best_practices/analyzer.rb', line 26 def initialize(path, ={}) @path = path || "." @options = end |
Instance Attribute Details
#runner ⇒ Object
Returns the value of attribute runner.
18 19 20 |
# File 'lib/rails_best_practices/analyzer.rb', line 18 def runner @runner end |
Instance Method Details
#analyze ⇒ Object
Analyze rails codes.
there are two steps to check rails codes,
-
prepare process, check all model and mailer files.
-
review process, check all files.
if there are violations to rails best practices, output them.
47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/rails_best_practices/analyzer.rb', line 47 def analyze @options["exclude"] ||= [] @options["only"] ||= [] @options["output-file"] ||= "rails_best_practices_output.html" Core::Runner.base_path = @path @runner = Core::Runner.new @runner.debug = true if @options["debug"] @runner.color = !@options["without-color"] @bar = ProgressBar.new('Source Codes', parse_files.size * 3) if ["lexical", "prepare", "review"].each { |process| send(:process, process) } @bar.finish if end |
#display_bar? ⇒ Boolean
62 63 64 |
# File 'lib/rails_best_practices/analyzer.rb', line 62 def !@options["debug"] && !@options["silent"] end |
#error_types ⇒ Object
unique error types.
252 253 254 |
# File 'lib/rails_best_practices/analyzer.rb', line 252 def error_types @runner.errors.map(&:type).uniq end |
#expand_dirs_to_files(*dirs) ⇒ Array
expand all files with extenstion rb, erb, haml, slim, builder and rxml under the dirs
124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/rails_best_practices/analyzer.rb', line 124 def *dirs extensions = ['rb', 'erb', 'rake', 'rhtml', 'haml', 'slim', 'builder', 'rxml'] dirs.flatten.map { |entry| next unless File.exist? entry if File.directory? entry Dir[File.join(entry, '**', "*.{#{extensions.join(',')}}")] else entry end }.flatten end |
#file_accept(files, patterns) ⇒ Object
accept specific files.
169 170 171 |
# File 'lib/rails_best_practices/analyzer.rb', line 169 def file_accept files, patterns files.reject { |file| !patterns.any? { |pattern| file =~ pattern } } end |
#file_ignore(files, pattern) ⇒ Array
ignore specific files.
161 162 163 |
# File 'lib/rails_best_practices/analyzer.rb', line 161 def file_ignore files, pattern files.reject { |file| file.index(pattern) } end |
#file_sort(files) ⇒ Array
sort files, models first, mailers, helpers, and then sort other files by characters.
models and mailers first as for prepare process.
144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/rails_best_practices/analyzer.rb', line 144 def file_sort files models = files.find_all { |file| file =~ Core::Check::MODEL_FILES } mailers = files.find_all { |file| file =~ Core::Check::MAILER_FILES } helpers = files.find_all { |file| file =~ Core::Check::HELPER_FILES } others = files.find_all { |file| file !~ Core::Check::MAILER_FILES && file !~ Core::Check::MODEL_FILES && file !~ Core::Check::HELPER_FILES } models.sort mailers.sort helpers.sort others.sort return models + mailers + helpers + others end |
#generate ⇒ Object
generate configuration yaml file.
32 33 34 |
# File 'lib/rails_best_practices/analyzer.rb', line 32 def generate FileUtils.cp DEFAULT_CONFIG, File.join(@path, 'config/rails_best_practices.yml') end |
#load_git_info ⇒ Object
load git commit and git username info.
200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
# File 'lib/rails_best_practices/analyzer.rb', line 200 def load_git_info = ProgressBar.new('Git Info', @runner.errors.size) if start = @runner.class.base_path =~ /\/$/ ? @runner.class.base_path.size : @runner.class.base_path.size + 1 @runner.errors.each do |error| git_info = `cd #{@runner.class.base_path}; git blame -L #{error.line_number.split(',').first},+1 #{error.filename[start..-1]}` unless git_info == "" git_commit, git_username = git_info.split(/\d{4}-\d{2}-\d{2}/).first.split("(") error.git_commit = git_commit.split(" ").first.strip error.git_username = git_username.strip end .inc if end .finish if end |
#load_hg_info ⇒ Object
load hg commit and hg username info.
185 186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/rails_best_practices/analyzer.rb', line 185 def load_hg_info = ProgressBar.new('Hg Info', @runner.errors.size) if @runner.errors.each do |error| hg_info = `cd #{@runner.class.base_path}; hg blame -lvcu #{error.filename[@runner.class.base_path.size..-1].gsub(/^\//, "")} | sed -n /:#{error.line_number.split(',').first}:/p` unless hg_info == "" hg_commit_username = hg_info.split(':')[0].strip error.hg_username = hg_commit_username.split(/\ /)[0..-2].join(' ') error.hg_commit = hg_commit_username.split(/\ /)[-1] end .inc if end .finish if end |
#output ⇒ Object
Output the analyze result.
67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/rails_best_practices/analyzer.rb', line 67 def output if @options["format"] == 'html' if @options["with-hg"] load_hg_info elsif @options["with-git"] load_git_info end output_html_errors else output_terminal_errors end end |
#output_html_errors ⇒ Object
output errors with html format.
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 |
# File 'lib/rails_best_practices/analyzer.rb', line 216 def output_html_errors require 'erubis' template = @options["template"] ? File.read(File.(@options["template"])) : File.read(File.join(File.dirname(__FILE__), "..", "..", "assets", "result.html.erb")) if @options["with-github"] last_commit_id = @options["last-commit-id"] ? @options["last-commit-id"] : `cd #{@runner.class.base_path}; git rev-parse HEAD`.chomp end File.open(@options["output-file"], "w+") do |file| eruby = Erubis::Eruby.new(template) file.puts eruby.evaluate( :errors => @runner.errors, :error_types => error_types, :textmate => @options["with-textmate"], :mvim => @options["with-mvim"], :github => @options["with-github"], :github_name => @options["github-name"], :last_commit_id => last_commit_id, :git => @options["with-git"], :hg => @options["with-hg"] ) end end |
#output_terminal_errors ⇒ Object
output errors on terminal.
174 175 176 177 178 179 180 181 182 |
# File 'lib/rails_best_practices/analyzer.rb', line 174 def output_terminal_errors @runner.errors.each { |error| plain_output(error.to_s, 'red') } plain_output("\nPlease go to http://rails-bestpractices.com to see more useful Rails Best Practices.", 'green') if @runner.errors.empty? plain_output("\nNo warning found. Cool!", 'green') else plain_output("\nFound #{@runner.errors.size} warnings.", 'red') end end |
#parse_files ⇒ Array
get all files for parsing.
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/rails_best_practices/analyzer.rb', line 97 def parse_files @parse_files ||= begin files = (@path) files = file_sort(files) if @options["only"].present? files = file_accept(files, @options["only"]) end # By default, tmp, vender, spec, test, features are ignored. ["vendor", "spec", "test", "features", "tmp"].each do |pattern| files = file_ignore(files, "#{pattern}/") unless @options[pattern] end # Exclude files based on exclude regexes if the option is set. @options["exclude"].each do |pattern| files = file_ignore(files, pattern) end files.compact end end |
#plain_output(message, color) ⇒ Object
plain output with color.
243 244 245 246 247 248 249 |
# File 'lib/rails_best_practices/analyzer.rb', line 243 def plain_output(, color) if @options["without-color"] puts else puts .send(color) end end |
#process(process) ⇒ Object
process lexical, prepare or reivew.
get all files for the process, analyze each file, and increment progress bar unless debug.
86 87 88 89 90 91 92 |
# File 'lib/rails_best_practices/analyzer.rb', line 86 def process(process) parse_files.each do |file| @runner.send("#{process}_file", file) @bar.inc if end @runner.send("after_#{process}") end |