# encoding: utf-8 require 'rails_best_practices/reviews/review' module RailsBestPractices module Reviews # Review a migration file to make sure to use say or say_with_time for customized data changes # to produce a more readable output. # # See the best practice detials here # http://rails-bestpractices.com/posts/46-use-say-and-say_with_time-in-migrations-to-make-a-useful-migration-log. # # Implementation: # # Review process: # check class method define nodes (self.up or self.down). # if there is a method call in the class method definition, # and the message of method call is not say, say_with_time and default migration methods # (such as add_column and create_table), then the method call should be wrapped by say or say_with_time. class UseSayWithTimeInMigrationsReview < Review interesting_nodes :defs interesting_files MIGRATION_FILES WITH_SAY_METHODS = %w(say say_with_time) def url "http://rails-bestpractices.com/posts/46-use-say-and-say_with_time-in-migrations-to-make-a-useful-migration-log" end # check a class method define node to see if there are method calls that need to be wrapped by say # or say_with_time. # # it will check the first block node, # if any method call whose message is not default migration methods in the block node, # then such method call should be wrapped by say or say_with_time def start_defs(node) node.body.statements.each do |child_node| next if child_node.grep_nodes_count(sexp_type: [:fcall, :command], message: WITH_SAY_METHODS) > 0 subject_node = if :method_add_block == child_node.sexp_type child_node[1] elsif :method_add_arg == child_node.sexp_type child_node[1] else child_node end if :call == subject_node.sexp_type add_error("use say with time in migrations", node.file, child_node.line) end end end end end end