Don't output the whole Rails::Railtie object

- ### Summary

  The terminal output on a Rails application running ruby 3 will be
  cluttered with thousands of lines if one inadventarly call a
  unexisting method.
  This happen in various places (IntegrationTest, when running a db
  migration ...).
  This is related to a change in ruby 3 when a NoMethodError is
  raised.

  ### Simple reproduction

  ```
  class A
    def initialize(session)
      @a = session
    end
  end

  test = A.new("*" * 36)
  test.dsad # undefined method `dsad' for #<A:0x00007f847d8494b0 @a="************************************"> (NoMethodError)
  # Note that the "#<A:0x00007f847d8494b0 @a="************************************">" part
  # is 65 chars long.

  test = test = A.new("*" * 37)
  test.dsad # undefined method `dsad' for #<A:0x00007fa8c38299c0> (NoMethodError)
  ```

  On Ruby < 3, the NoMethodError message (everything starting from the
  "#" char) could only be 65 characters long. If it was above that
  ruby would only output the name of the class and its address.

  On Ruby >= 3, that limitation has been removed and the message can
  be any length long.

  ### On Rails

  Anytime a method is called on a object that holds the entire
  Rails::Application, the terminal would output the entire application
  which is annoying be can be dangerous because it will leak
  everything containing the credentials (stored inside the Application
  object).
This commit is contained in:
Edouard CHIN 2022-02-21 01:07:19 +01:00
parent 6719f02d25
commit e60dd826c0
2 changed files with 17 additions and 0 deletions

@ -247,6 +247,10 @@ def initialize # :nodoc:
end
end
def inspect # :nodoc:
"#<#{self.class.name}>"
end
def configure(&block) # :nodoc:
instance_eval(&block)
end

@ -224,5 +224,18 @@ class MyTie < Rails::Railtie
Rails.env = original_env
assert_equal(original_env, Rails.env)
end
test "Railtie object isn't output when a NoMethodError is raised" do
class Foo < Rails::Railtie
config.foo = ActiveSupport::OrderedOptions.new
config.foo.greetings = "hello"
end
error = assert_raises(NoMethodError) do
Foo.instance.abc
end
assert_equal("undefined method `abc' for #<RailtiesTest::RailtieTest::Foo>", error.original_message)
end
end
end