Skip to content

Commit

Permalink
Elaborate doc for attribute read and write methods [ci-skip]
Browse files Browse the repository at this point in the history
This commit elaborates the documentation for the Active Record `#[]`,
`#[]=`, and `#read_attribute` methods, including adding pointers to
`ActiveModel::Type` for information about specific type casting
behavior.  In turn, this commit removes the note about casting empty
strings from the `#write_attribute` method.
  • Loading branch information
jonathanhefner committed Nov 15, 2022
1 parent 8d9f525 commit 20bc41a
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 20 deletions.
32 changes: 18 additions & 14 deletions activerecord/lib/active_record/attribute_methods.rb
Expand Up @@ -310,36 +310,40 @@ def attribute_present?(attr_name)
!value.nil? && !(value.respond_to?(:empty?) && value.empty?)
end

# Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example,
# "2004-12-12" in a date column is cast to a date object, like <tt>Date.new(2004, 12, 12)</tt>). It raises
# ActiveModel::MissingAttributeError if the identified attribute is missing.
#
# Note: +:id+ is always present.
# Returns the value of the attribute identified by +attr_name+ after it has
# been type cast. (For information about specific type casting behavior, see
# the types under ActiveModel::Type.)
#
# class Person < ActiveRecord::Base
# belongs_to :organization
# end
#
# person = Person.new(name: 'Francesco', age: '22')
# person[:name] # => "Francesco"
# person[:age] # => 22
# person = Person.new(name: "Francesco", date_of_birth: "2004-12-12")
# person[:name] # => "Francesco"
# person[:date_of_birth] # => Date.new(2004, 12, 12)
# person[:organization_id] # => nil
#
# Raises ActiveModel::MissingAttributeError if the attribute is missing.
# Note, however, that the +id+ attribute will never be considered missing.
#
# person = Person.select('id').first
# person[:name] # => ActiveModel::MissingAttributeError: missing attribute: name
# person = Person.select(:name).first
# person[:name] # => "Francesco"
# person[:date_of_birth] # => ActiveModel::MissingAttributeError: missing attribute: date_of_birth
# person[:organization_id] # => ActiveModel::MissingAttributeError: missing attribute: organization_id
# person[:id] # => nil
def [](attr_name)
read_attribute(attr_name) { |n| missing_attribute(n, caller) }
end

# Updates the attribute identified by <tt>attr_name</tt> with the specified +value+.
# Updates the attribute identified by +attr_name+ using the specified
# +value+. The attribute value will be type cast upon being read.
#
# class Person < ActiveRecord::Base
# end
#
# person = Person.new
# person[:age] = '22'
# person[:age] # => 22
# person[:age].class # => Integer
# person[:date_of_birth] = "2004-12-12"
# person[:date_of_birth] # => Date.new(2004, 12, 12)
def []=(attr_name, value)
write_attribute(attr_name, value)
end
Expand Down
7 changes: 4 additions & 3 deletions activerecord/lib/active_record/attribute_methods/read.rb
Expand Up @@ -21,9 +21,10 @@ def define_method_attribute(name, owner:)
end
end

# Returns the value of the attribute identified by <tt>attr_name</tt> after
# it has been typecast (for example, "2004-12-12" in a date column is cast
# to a date object, like <tt>Date.new(2004, 12, 12)</tt>).
# Returns the value of the attribute identified by +attr_name+ after it
# has been type cast. For example, a date attribute will cast "2004-12-12"
# to <tt>Date.new(2004, 12, 12)</tt>. (For information about specific type
# casting behavior, see the types under ActiveModel::Type.)
def read_attribute(attr_name, &block)
name = attr_name.to_s
name = self.class.attribute_aliases[name] || name
Expand Down
5 changes: 2 additions & 3 deletions activerecord/lib/active_record/attribute_methods/write.rb
Expand Up @@ -25,9 +25,8 @@ def define_method_attribute=(name, owner:)
end
end

# Updates the attribute identified by <tt>attr_name</tt> with the
# specified +value+. Empty strings for Integer and Float columns are
# turned into +nil+.
# Updates the attribute identified by +attr_name+ using the specified
# +value+. The attribute value will be type cast upon being read.
def write_attribute(attr_name, value)
name = attr_name.to_s
name = self.class.attribute_aliases[name] || name
Expand Down

0 comments on commit 20bc41a

Please sign in to comment.