You know everything about pretending to be an ActiveRecord::Base
object,
and especially the bit about ActiveRecord::Errors. That part’s really cool.
What we are doing here is making an object that quacks like an
ActiveRecord::Base
object but has no database table backing it. As examples: a
search object, a credit card object, or a remote user object. To do this, you
need id
, new_record?
, and the attributes must work in a specific fashion.
You can also have errors
produce an ActiveRecord::Errors
instance so user
errors will show in forms and whatnot.
However you may not have noticed that Rails 2.3.4 broke API compatibility for ActiveRecord::Errors
. If
your ActiveRecord::Base
-like class provides an #errors
instance method, it
must now provide these class methods:
self_and_descendants_from_active_record
, which produces an array of classes.human_name
, which takes an optional hash and produces a string.human_attribute_name
, which takes a string and optional hash and produces a string.
The last two of these methods are useful in your day-to-day Rails knowledge (the
first is an internal, undocumented method used by Rails to produce the class
itself and its parents, up to and excluding ActiveRecord::Base
).
human_name
is used to produce a humanized string representing the class/table
name. If your class is named AuthenticationRecord
, .human_name
will produce
"Authenticationrecord"
. Any options you pass to this are normally sent to
I18n.translate
.
human_attribute_name
is used to map an attribute to a human-readable string.
For example, the attribute created_at
is mapped to "Created at"
. Any options
passed to this are normally sent to I18n.translate
.
Here are some tests that need to pass now:
class SearchTest < ActiveSupport::TestCase
should "conform to the ActiveRecord::Errors interface" do
assert_respond_to Search, :self_and_descendants_from_active_record
assert_respond_to Search, :human_name
assert_respond_to Search, :human_attribute_name
assert_equal [Search], Search.self_and_descendants_from_active_record
assert_equal "Search", Search.human_name
assert_equal "Published at", Search.human_attribute_name('published_at')
end
end