module ActiveModel::AttributeMethods::AttrNames

def self.define_attribute_accessor_method(owner, attr_name, writer: false)

key the @attributes in read_attribute.
Making it frozen means that it doesn't get duped when used to
to allocate an object on each call to the attribute method.
the attribute name. Using a constant means that we do not have
We are also defining a constant to hold the frozen string of

it to what we want.
the __temp__ identifier, and then use alias method to rename
'my_column(omg)'. So to work around this we first define with
characters that are not allowed in normal method names (like
But sometimes the database might return columns with

define_method, because define_method is slower on dispatch.
We want to generate the methods via module_eval rather than
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}'"
  else
    safe_name = attr_name.unpack1("h*")
    const_name = "ATTR_#{safe_name}"
    const_set(const_name, attr_name) unless const_defined?(const_name)
    temp_method_name = "__temp__#{safe_name}#{'=' if writer}"
    attr_name_expr = "::ActiveModel::AttributeMethods::AttrNames::#{const_name}"
    yield temp_method_name, attr_name_expr
  end
end