Module: ActiveModel::AttributeMethods::AttrNames
- Defined in:
- activemodel/lib/active_model/attribute_methods.rb
Overview
:nodoc:
Constant Summary collapse
- DEF_SAFE_NAME =
/\A[a-zA-Z_]\w*\z/
Class Method Summary collapse
-
.define_attribute_accessor_method(owner, attr_name, writer: false) ⇒ Object
We want to generate the methods via module_eval rather than define_method, because define_method is slower on dispatch.
Class Method Details
.define_attribute_accessor_method(owner, attr_name, writer: false) ⇒ Object
We want to generate the methods via module_eval rather than define_method, because define_method is slower on dispatch.
But sometimes the database might return columns with characters that are not allowed in normal method names (like ‘my_column(omg)’. So to work around this we first define with the __temp__ identifier, and then use alias method to rename it to what we want.
We are also defining a constant to hold the frozen string of the attribute name. Using a constant means that we do not have 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.
528 529 530 531 532 533 534 535 536 537 538 539 540 |
# File 'activemodel/lib/active_model/attribute_methods.rb', line 528 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 |