Class: RailsBestPractices::Reviews::AlwaysAddDbIndexReview

Inherits:
Review show all
Includes:
Afterable
Defined in:
lib/rails_best_practices/reviews/always_add_db_index_review.rb

Overview

Review db/schema.rb file to make sure every reference key has a database index.

See the best practice details here rails-bestpractices.com/posts/21-always-add-db-index

Implementation:

Review process:

only check the command and command_calls nodes and at the end of review process,
if the subject of command node is "create_table", then remember the table names
if the subject of command_call node is "integer" and suffix with id, then remember it as foreign key
if the sujbect of command_call node is "string", the name of it is _type suffixed and there is an integer column _id suffixed, then remember it as polymorphic foreign key
if the subject of command node is "add_index", then remember the index columns
after all of these, at the end of review process

    ActiveRecord::Schema.define(:version => 20101201111111) do
      ......
    end

if there are any foreign keys not existed in index columns,
then the foreign keys should add db index.

Constant Summary

Constants inherited from Core::Check

Core::Check::ALL_FILES, Core::Check::CONTROLLER_FILES, Core::Check::DEPLOY_FILES, Core::Check::HELPER_FILES, Core::Check::MAILER_FILES, Core::Check::MIGRATION_FILES, Core::Check::MODEL_FILES, Core::Check::PARTIAL_VIEW_FILES, Core::Check::ROUTE_FILES, Core::Check::SCHEMA_FILE, Core::Check::VIEW_FILES

Instance Method Summary collapse

Methods inherited from Review

#model_associations, #model_attributes, #models, #remember_variable_use_count, #reset_variable_use_count, #variable, #variable_use_count

Methods inherited from Core::Check

add_callback, #add_error, #after_prepare, callbacks, #errors, #increment_total_files_checked!, #interesting_files, interesting_files, #interesting_nodes, interesting_nodes, #method_missing, #node_end, #node_start, #parse_file?, #result, #total_files_checked

Constructor Details

#initializeAlwaysAddDbIndexReview

Returns a new instance of AlwaysAddDbIndexReview.



36
37
38
39
40
41
# File 'lib/rails_best_practices/reviews/always_add_db_index_review.rb', line 36

def initialize
  super
  @index_columns = {}
  @foreign_keys = {}
  @table_nodes = {}
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class RailsBestPractices::Core::Check

Instance Method Details

#after_reviewObject

check at the end of review process.

compare foreign keys and index columns, if there are any foreign keys not existed in index columns, then we should add db index for that foreign keys.



76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/rails_best_practices/reviews/always_add_db_index_review.rb', line 76

def after_review
  remove_table_not_exist_foreign_keys
  remove_only_type_foreign_keys
  combine_polymorphic_foreign_keys
  @foreign_keys.each do |table, foreign_key|
    table_node = @table_nodes[table]
    foreign_key.each do |column|
      if indexed?(table, column)
        add_error "always add db index (#{table} => [#{Array(column).join(', ')}])", table_node.file, table_node.line
      end
    end
  end
end

#start_command(node) ⇒ Object

check command node.

if the message of command node is “integer”, then remember it as a foreign key of last create table name.

if the message of command node is “type” and the name of argument is _type suffixed, then remember it with _id suffixed column as polymorphic foreign key.



62
63
64
65
66
67
68
69
# File 'lib/rails_best_practices/reviews/always_add_db_index_review.rb', line 62

def start_command(node)
  case node.message.to_s
  when "create_table"
    remember_table_nodes(node)
  when "add_index"
    remember_index_columns(node)
  end
end

#start_command_call(node) ⇒ Object

check command_call node.

if the message of command_call node is “create_table”, then remember the table name. if the message of command_call node is “add_index”, then remember it as index columns.



47
48
49
50
51
52
53
# File 'lib/rails_best_practices/reviews/always_add_db_index_review.rb', line 47

def start_command_call(node)
  case node.message.to_s
  when "integer", "string"
    remember_foreign_key_columns(node)
  else
  end
end

#urlObject



32
33
34
# File 'lib/rails_best_practices/reviews/always_add_db_index_review.rb', line 32

def url
  "http://rails-bestpractices.com/posts/21-always-add-db-index"
end