-
Notifications
You must be signed in to change notification settings - Fork 21.9k
Closed
Labels
Description
Steps to reproduce
# frozen_string_literal: true
require "bundler/inline"
gemfile(true) do
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
gem "rails", github: "rails/rails", branch: "main"
end
require "action_controller/railtie"
require 'rails/test_help'
class TestApp < Rails::Application
config.root = __dir__
config.hosts << "www.example.com"
secrets.secret_key_base = "secret_key_base"
config.logger = Logger.new($stdout)
Rails.logger = config.logger
routes.draw do
get "/child_index" => "child#index"
get "/child_show" => "child#show"
get "/base_index" => "base#index"
get "/base_show" => "base#show"
end
end
class BaseController < ActionController::Base
def index
render plain: "BaseController#index"
end
def show
render plain: "BaseController#show"
end
end
class ChildController < BaseController
def index
render plain: "ChildController#index"
end
def show
render plain: "ChildController#show"
end
end
module ChildControllerDecorator
def self.prepended(base)
base.before_action :set_instance_var, only: :index
end
def set_instance_var
@instance_var = :index
end
end
ChildController.prepend(ChildControllerDecorator)
module BaseControllerDecorator
def self.prepended(base)
base.before_action :set_instance_var, only: :show
end
def set_instance_var
@instance_var = :show
end
end
BaseController.prepend(BaseControllerDecorator)
require "minitest/autorun"
class ChildControllerTest < ActionDispatch::IntegrationTest
test "instance var should equal to :index when child index action is invoked" do
get "/child_index"
assert_equal :index, @controller.instance_variable_get(:@instance_var)
end
test "instance var should equal to :nil when child show action is invoked" do
get "/child_show"
assert_equal nil, @controller.instance_variable_get(:@instance_var)
end
private
def app
Rails.application
end
end
Expected behavior
ChildController's before action should not be overridden by parent. In the test case, @instance_var should be set to :index
, and only be set when index
action is executed.
Actual behavior
ChildController's before action is overridden by parent. wrong execution condition and value.
System configuration
Rails version: main
branch
Ruby version: 2.7.2
In order to figure it out, I read the source code. It seems every time the before_action
or prepend_before_action
is executed, there is a operation called remove_duplicates
which remove the filters with the same name from itself and its descendants. It should not remove filters with the same name from its descendants, right?
J-Swift