Also batch attribute readers and writers

This commit is contained in:
Jean Boussier 2020-05-01 12:21:16 +02:00
parent 348e142b26
commit d12418a776
4 changed files with 30 additions and 31 deletions

@ -294,7 +294,7 @@ def define_attribute_method(attr_name, _owner: generated_attribute_methods)
generate_method = "define_method_#{matcher.target}"
if respond_to?(generate_method, true)
send(generate_method, attr_name.to_s)
send(generate_method, attr_name.to_s, owner: owner)
else
define_proxy_call true, owner, method_name, matcher.target, attr_name.to_s
end
@ -354,14 +354,23 @@ def initialize(owner, path, line)
@path = path
@line = line
@sources = ["# frozen_string_literal: true\n"]
@renames = {}
end
def <<(source_line)
@sources << source_line
end
def rename_method(old_name, new_name)
@renames[old_name] = new_name
end
def execute
@owner.module_eval(@sources.join(";"), @path, @line - 1)
@renames.each do |old_name, new_name|
@owner.alias_method new_name, old_name
@owner.undef_method old_name
end
end
end
private_constant :CodeGenerator
@ -527,7 +536,7 @@ module AttrNames # :nodoc:
# to allocate an object on each call to the attribute method.
# Making it frozen means that it doesn't get duped when used to
# key the @attributes in read_attribute.
def self.define_attribute_accessor_method(mod, attr_name, writer: false)
def self.define_attribute_accessor_method(owner, attr_name, writer: false)
method_name = "#{attr_name}#{'=' if writer}"
if attr_name.ascii_only? && DEF_SAFE_NAME.match?(attr_name)
yield method_name, "'#{attr_name}'"
@ -538,8 +547,7 @@ def self.define_attribute_accessor_method(mod, attr_name, writer: false)
temp_method_name = "__temp__#{safe_name}#{'=' if writer}"
attr_name_expr = "::ActiveModel::AttributeMethods::AttrNames::#{const_name}"
yield temp_method_name, attr_name_expr
mod.alias_method method_name, temp_method_name
mod.undef_method temp_method_name
owner.rename_method(temp_method_name, method_name)
end
end
end

@ -42,17 +42,14 @@ def attribute_names
end
private
def define_method_attribute=(name)
def define_method_attribute=(name, owner:)
ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
generated_attribute_methods, name, writer: true,
owner, name, writer: true,
) do |temp_method_name, attr_name_expr|
generated_attribute_methods.module_eval <<-RUBY, __FILE__, __LINE__ + 1
# frozen_string_literal: true
def #{temp_method_name}(value)
name = #{attr_name_expr}
write_attribute(name, value)
end
RUBY
owner <<
"def #{temp_method_name}(value)" <<
" write_attribute(#{attr_name_expr}, value)" <<
"end"
end
end

@ -7,17 +7,14 @@ module Read
module ClassMethods # :nodoc:
private
def define_method_attribute(name)
def define_method_attribute(name, owner:)
ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
generated_attribute_methods, name
owner, name
) do |temp_method_name, attr_name_expr|
generated_attribute_methods.module_eval <<-RUBY, __FILE__, __LINE__ + 1
# frozen_string_literal: true
def #{temp_method_name}
name = #{attr_name_expr}
_read_attribute(name) { |n| missing_attribute(n, caller) }
end
RUBY
owner <<
"def #{temp_method_name}" <<
" _read_attribute(#{attr_name_expr}) { |n| missing_attribute(n, caller) }" <<
"end"
end
end
end

@ -11,17 +11,14 @@ module Write
module ClassMethods # :nodoc:
private
def define_method_attribute=(name)
def define_method_attribute=(name, owner:)
ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
generated_attribute_methods, name, writer: true,
owner, name, writer: true,
) do |temp_method_name, attr_name_expr|
generated_attribute_methods.module_eval <<-RUBY, __FILE__, __LINE__ + 1
# frozen_string_literal: true
def #{temp_method_name}(value)
name = #{attr_name_expr}
_write_attribute(name, value)
end
RUBY
owner <<
"def #{temp_method_name}(value)" <<
" _write_attribute(#{attr_name_expr}, value)" <<
"end"
end
end
end