Skip to content

Commit

Permalink
Simplify attr_internal_define
Browse files Browse the repository at this point in the history
The `@` prefix is always stripped, so might as well not require it.

For backward compatibility reasons we still handle the prefix for now,
but we eagerly strip it and emit a deprecation.
  • Loading branch information
byroot committed Oct 31, 2023
1 parent 5a47bb8 commit db92ea3
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 10 deletions.
23 changes: 17 additions & 6 deletions activesupport/lib/active_support/core_ext/module/attr_internal.rb
Expand Up @@ -19,16 +19,27 @@ def attr_internal_accessor(*attrs)
end
alias_method :attr_internal, :attr_internal_accessor

class << self; attr_accessor :attr_internal_naming_format end
self.attr_internal_naming_format = "@_%s"
class << self
attr_reader :attr_internal_naming_format

private
def attr_internal_ivar_name(attr)
Module.attr_internal_naming_format % attr
def attr_internal_naming_format=(format)
if format.start_with?("@")
ActiveSupport.deprecator.warn <<~MESSAGE
Setting `attr_internal_naming_format` with a `@` prefix is deprecated and will be removed in Rails 7.2.
You can simply replace #{format.inspect} by #{format.delete_prefix("@").inspect}.
MESSAGE

format = format.delete_prefix("@")
end
@attr_internal_naming_format = format
end
end
self.attr_internal_naming_format = "_%s"

private
def attr_internal_define(attr_name, type)
internal_name = attr_internal_ivar_name(attr_name).delete_prefix("@")
internal_name = Module.attr_internal_naming_format % attr_name
# use native attr_* methods as they are faster on some Ruby implementations
public_send("attr_#{type}", internal_name)
attr_name, internal_name = "#{attr_name}=", "#{internal_name}=" if type == :writer
Expand Down
18 changes: 14 additions & 4 deletions activesupport/test/core_ext/module/attr_internal_test.rb
Expand Up @@ -7,6 +7,11 @@ class AttrInternalTest < ActiveSupport::TestCase
def setup
@target = Class.new
@instance = @target.new
@naming_format_was = Module.attr_internal_naming_format
end

def teardown
Module.attr_internal_naming_format = @naming_format_was
end

def test_reader
Expand Down Expand Up @@ -39,17 +44,22 @@ def test_accessor
assert_nothing_raised { assert_equal 1, @instance.foo }
end

def test_naming_format_deprecation
assert_equal "_%s", Module.attr_internal_naming_format
assert_deprecated(ActiveSupport.deprecator) do
Module.attr_internal_naming_format = "@___%s"
end
assert_equal "___%s", Module.attr_internal_naming_format
end

def test_naming_format
assert_equal "@_%s", Module.attr_internal_naming_format
assert_nothing_raised { Module.attr_internal_naming_format = "@abc%sdef" }
assert_nothing_raised { Module.attr_internal_naming_format = "abc%sdef" }
@target.attr_internal :foo

assert_not @instance.instance_variable_defined?("@_foo")
assert_not @instance.instance_variable_defined?("@abcfoodef")
assert_nothing_raised { @instance.foo = 1 }
assert_not @instance.instance_variable_defined?("@_foo")
assert @instance.instance_variable_defined?("@abcfoodef")
ensure
Module.attr_internal_naming_format = "@_%s"
end
end

0 comments on commit db92ea3

Please sign in to comment.