# frozen_string_literal: true module RailsBestPractices module Prepares # Remember controllers and controller methods class ControllerPrepare < Core::Check include Core::Check::Classable include Core::Check::InheritedResourcesable include Core::Check::Accessable interesting_nodes :class, :var_ref, :vcall, :command, :def interesting_files CONTROLLER_FILES DEFAULT_ACTIONS = %w[index show new create edit update destroy].freeze def initialize @controllers = Prepares.controllers @methods = Prepares.controller_methods @helpers = Prepares.helpers @inherited_resources = false end # check class node to remember the class name. # also check if the controller is inherit from InheritedResources::Base. add_callback :start_class do |_node| @controllers << @klass @current_controller_name = @klass.to_s @actions = DEFAULT_ACTIONS if @inherited_resources end # remember the action names at the end of class node if the controller is a InheritedResources. add_callback :end_class do |node| if @inherited_resources && @current_controller_name != 'ApplicationController' @actions.each do |action| @methods.add_method(@current_controller_name, action, 'file' => node.file, 'line_number' => node.line_number) end end end # check if there is a DSL call inherit_resources. add_callback :start_var_ref do |_node| @actions = DEFAULT_ACTIONS if @inherited_resources end # check if there is a DSL call inherit_resources. add_callback :start_vcall do |_node| @actions = DEFAULT_ACTIONS if @inherited_resources end # restrict actions for inherited_resources add_callback :start_command do |node| if node.message.to_s == 'include' @helpers.add_module_descendant(node.arguments.all.first.to_s, current_class_name) elsif @inherited_resources && node.message.to_s == 'actions' if node.arguments.all.first.to_s == 'all' @actions = DEFAULT_ACTIONS option_argument = node.arguments.all[1] if option_argument && option_argument.sexp_type == :bare_assoc_hash && option_argument.hash_value('except') @actions -= option_argument.hash_value('except').to_object end else @actions = node.arguments.all.map(&:to_s) end end end # check def node to remember all methods. # # the remembered methods (@methods) are like # { # "PostsController" => { # "save" => {"file" => "app/controllers/posts_controller.rb", "line_number" => 10, "unused" => false}, # "find" => {"file" => "app/controllers/posts_controller.rb", "line_number" => 10, "unused" => false} # }, # "CommentsController" => { # "create" => {"file" => "app/controllers/comments_controller.rb", "line_number" => 10, "unused" => false}, # } # } add_callback :start_def do |node| method_name = node.method_name.to_s @methods.add_method(current_class_name, method_name, { 'file' => node.file, 'line_number' => node.line_number }, current_access_control) end # ask Reviews::RemoveUnusedMoethodsInHelperReview to check the controllers who include helpers. add_callback :after_check do descendants = @helpers.map(&:descendants).flatten if descendants.present? Reviews::RemoveUnusedMethodsInHelpersReview.interesting_files *descendants.map { |descendant| /#{descendant.underscore}/ } end end end end end