Skip to content

Commit

Permalink
Merge pull request #8056 from frodsan/fix_issue_missing_attribute
Browse files Browse the repository at this point in the history
AR::AttributeMethods#[] raises AM::AttributeMissingError for missing attributes
  • Loading branch information
rafaelfranca committed Oct 28, 2012
2 parents e46a8d8 + 10f6f90 commit c82f0d7
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 3 deletions.
25 changes: 24 additions & 1 deletion activerecord/CHANGELOG.md
@@ -1,5 +1,28 @@
## Rails 4.0.0 (unreleased) ##

* `ActiveRecord::AttributeMethods#[]` raises `ActiveModel::MissingAttributeError`
error if the given attribute is missing. Fixes #5433.

class Person < ActiveRecord::Base
belongs_to :company
end

# Before:
person = Person.select('id').first
person[:name] # => nil
person.name # => ActiveModel::MissingAttributeError: missing_attribute: name
person[:company_id] # => nil
person.company # => nil

# After:
person = Person.select('id').first
person[:name] # => ActiveModel::MissingAttributeError: missing_attribute: name
person.name # => ActiveModel::MissingAttributeError: missing_attribute: name
person[:company_id] # => ActiveModel::MissingAttributeError: missing_attribute: company_id
person.company # => ActiveModel::MissingAttributeError: missing_attribute: company_id

*Francesco Rodriguez*

* Small binary fields use the `VARBINARY` MySQL type, instead of `TINYBLOB`.

*Victor Costan*
Expand Down Expand Up @@ -51,7 +74,7 @@

*Scott Willson*

* Fix bug where sum(expression) returns string '0' for no matching records
* Fix bug where sum(expression) returns string '0' for no matching records.
Fixes #7439

*Tim Macfarlane*
Expand Down
10 changes: 8 additions & 2 deletions activerecord/lib/active_record/attribute_methods.rb
Expand Up @@ -266,16 +266,22 @@ def column_for_attribute(name)

# Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example,
# "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)).
# (Alias for the protected <tt>read_attribute</tt> method).
# (Alias for the protected <tt>read_attribute</tt> method). It raises an <tt>ActiveModel::MissingAttributeError</tt>
# error if the identified attribute is missing.
#
# class Person < ActiveRecord::Base
# belongs_to :organization
# end
#
# person = Person.new(name: 'Francesco', age: '22'
# person[:name] # => "Francesco"
# person[:age] # => 22
#
# person = Person.select('id').first
# person[:name] # => ActiveModel::MissingAttributeError: missing attribute: name
# person[:organization_id] # => ActiveModel::MissingAttributeError: missing attribute: organization_id
def [](attr_name)
read_attribute(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+.
Expand Down
6 changes: 6 additions & 0 deletions activerecord/test/cases/attribute_methods_test.rb
Expand Up @@ -287,6 +287,12 @@ def test_read_attribute
assert_equal "Don't change the topic", topic[:title]
end

def test_read_attribute_raises_missing_attribute_error_when_not_exists
computer = Computer.select('id').first
assert_raises(ActiveModel::MissingAttributeError) { computer[:developer] }
assert_raises(ActiveModel::MissingAttributeError) { computer[:extendedWarranty] }
end

def test_read_attribute_when_false
topic = topics(:first)
topic.approved = false
Expand Down

0 comments on commit c82f0d7

Please sign in to comment.