class RailsBestPractices::Core::Runner

Runner is the main class, it can check source code of a filename with all checks (according to the configuration).

the check process is partitioned into two parts,

  1. prepare process, it will do some preparations for further checking, such as remember the model associations.

  2. review process, it does real check, if the source code violates some best practices, the violations will be notified.

Attributes

base_path[W]
config_path[W]
checks[R]

Public Class Methods

base_path() click to toggle source

get the base path, by default, the base path is current path.

@return [String] the base path

# File lib/rails_best_practices/core/runner.rb, line 29
def base_path
  @base_path || '.'
end
config_path() click to toggle source

get the configuration path, if will default to config/rails_best_practices.yml

@return [String] the config path

# File lib/rails_best_practices/core/runner.rb, line 36
def config_path
  custom_config = @config_path || File.join(Runner.base_path, 'config/rails_best_practices.yml')
  File.exist?(custom_config) ? custom_config : RailsBestPractices::Analyzer::DEFAULT_CONFIG
end
new(options = {}) click to toggle source

initialize the runner.

@param [Hash] options pass the prepares and reviews.

# File lib/rails_best_practices/core/runner.rb, line 45
def initialize(options = {})
  @config = self.class.config_path

  lexicals = Array(options[:lexicals])
  prepares = Array(options[:prepares])
  reviews = Array(options[:reviews])

  checks_loader = ChecksLoader.new(@config)
  @lexicals = lexicals.empty? ? checks_loader.load_lexicals : lexicals
  @prepares = prepares.empty? ? load_prepares : prepares
  @reviews = reviews.empty? ? checks_loader.load_reviews : reviews
  load_plugin_reviews if reviews.empty?

  @lexical_checker ||= CodeAnalyzer::CheckingVisitor::Plain.new(checkers: @lexicals)
  @plain_prepare_checker ||=
    CodeAnalyzer::CheckingVisitor::Plain.new(
      checkers: @prepares.select { |checker| checker.is_a? Prepares::GemfilePrepare }
    )
  @default_prepare_checker ||=
    CodeAnalyzer::CheckingVisitor::Default.new(
      checkers: @prepares.reject { |checker| checker.is_a? Prepares::GemfilePrepare }
    )
  @review_checker ||= CodeAnalyzer::CheckingVisitor::Default.new(checkers: @reviews)

  @inlnie_disable ||= InlineDisables::InlineDisable.new
  @inline_disable_checker ||= CodeAnalyzer::CheckingVisitor::Plain.new(checkers: [@inlnie_disable])
end

Public Instance Methods

after_inline_disable() click to toggle source
# File lib/rails_best_practices/core/runner.rb, line 121
def after_inline_disable
  @inline_disable_checker.after_check
end
after_lexical() click to toggle source
# File lib/rails_best_practices/core/runner.rb, line 81
def after_lexical
  @lexical_checker.after_check
end
after_prepare() click to toggle source
# File lib/rails_best_practices/core/runner.rb, line 94
def after_prepare
  @plain_prepare_checker.after_check
  @default_prepare_checker.after_check
end
after_review() click to toggle source
# File lib/rails_best_practices/core/runner.rb, line 108
def after_review
  @review_checker.after_check
end
errors() click to toggle source

get all errors from lexicals and reviews.

@return [Array] all errors from lexicals and reviews

# File lib/rails_best_practices/core/runner.rb, line 128
def errors
  @errors ||= begin
    reported_errors = (@reviews + @lexicals).collect(&:errors).flatten
    reported_errors.reject { |error| @inlnie_disable.disabled?(error) }
  end
end
inline_disable(filename, content) click to toggle source

disable check by inline comment the file.

@param [String] filename of the file @param [String] content of the file

# File lib/rails_best_practices/core/runner.rb, line 116
def inline_disable(filename, content)
  content = parse_html_template(filename, content)
  @inline_disable_checker.check(filename, content)
end
lexical(filename, content) click to toggle source

lexical analysis the file.

@param [String] filename of the file @param [String] content of the file

# File lib/rails_best_practices/core/runner.rb, line 77
def lexical(filename, content)
  @lexical_checker.check(filename, content)
end
prepare(filename, content) click to toggle source

prepare the file.

@param [String] filename of the file @param [String] content of the file

# File lib/rails_best_practices/core/runner.rb, line 89
def prepare(filename, content)
  @plain_prepare_checker.check(filename, content)
  @default_prepare_checker.check(filename, content)
end
review(filename, content) click to toggle source

review the file.

@param [String] filename of the file @param [String] content of the file

# File lib/rails_best_practices/core/runner.rb, line 103
def review(filename, content)
  content = parse_html_template(filename, content)
  @review_checker.check(filename, content)
end

Private Instance Methods

load_plugin_reviews() click to toggle source

load all plugin reviews.

# File lib/rails_best_practices/core/runner.rb, line 174
def load_plugin_reviews
  plugins = File.join(Runner.base_path, 'lib', 'rails_best_practices', 'plugins', 'reviews')
  if File.directory?(plugins)
    Dir[File.expand_path(File.join(plugins, '*.rb'))].each do |review|
      require review
    end
    if RailsBestPractices.constants.map(&:to_sym).include? :Plugins
      RailsBestPractices::Plugins::Reviews.constants.each do |review|
        @reviews << RailsBestPractices::Plugins::Reviews.const_get(review).new
      end
    end
  end
end
load_prepares() click to toggle source

load all prepares.

# File lib/rails_best_practices/core/runner.rb, line 169
def load_prepares
  Prepares.constants.map { |prepare| Prepares.const_get(prepare).new }
end
parse_html_template(filename, content) click to toggle source

parse html template code, erb, haml and slim.

@param [String] filename is the filename of the erb, haml or slim code. @param [String] content is the source code of erb, haml or slim file.

# File lib/rails_best_practices/core/runner.rb, line 141
def parse_html_template(filename, content)
  if filename =~ /.*\.erb$|.*\.rhtml$/
    content = Erubis::OnlyRuby.new(content).src
  elsif filename =~ /.*\.haml$/
    begin
      require 'haml'
      content = Haml::Engine.new(content).precompiled
      # remove \xxx characters
      content.gsub!(/\\\d{3}/, '')
    rescue LoadError
      raise "In order to parse #{filename}, please install the haml gem"
    rescue Haml::Error, SyntaxError
      # do nothing, just ignore the wrong haml files.
    end
  elsif filename =~ /.*\.slim$/
    begin
      require 'slim'
      content = Slim::Engine.new.call(content)
    rescue LoadError
      raise "In order to parse #{filename}, please install the slim gem"
    rescue SyntaxError
      # do nothing, just ignore the wrong slim files
    end
  end
  content
end