I have a model with some attributes and a virtual attribute. This virtual attribute is used to make a checkbox in the creation form.
class Thing < ActiveRecord::Base
attr_accessor :foo
attr_accessible :foo
end
Since the field is a checkbox in the form, the foo
attribute will receive '0'
or '1'
as value. I would like it to be a boolean because of the following code:
class Thing < ActiveRecord::Base
attr_accessor :foo
attr_accessible :foo
before_validation :set_default_bar
private
def set_default_bar
self.bar = 'Hello' if foo
end
end
The problem here is that the condition will be true even when foo
is '0'
. I would like to use the ActiveRecord type casting mechanism but the only I found to do it is the following:
class Thing < ActiveRecord::Base
attr_reader :foo
attr_accessible :foo
before_validation :set_default_bar
def foo=(value)
@foo = ActiveRecord::ConnectionAdapters::Column.value_to_boolean(value)
end
private
def set_default_bar
self.bar = 'Hello' if foo
end
end
But I feel dirty doing it that way. Is there a better alternative without re-writing the conversion method ?
Thanks
What is 'Virtual Attribute'? The Virtual Attribute is a class attribute, which has no representation in the database. It becomes available after object initialization and remains alive while the object itself is available (like the instance methods).
The active record pattern is an approach to accessing data in a database. A database table or view is wrapped into a class. Thus, an object instance is tied to a single row in the table. After creation of an object, a new row is added to the table upon save.
Active Record facilitates the creation and use of business objects whose data requires persistent storage to a database. It is an implementation of the Active Record pattern which itself is a description of an Object Relational Mapping system.
What is ActiveRecord? ActiveRecord is an ORM. It's a layer of Ruby code that runs between your database and your logic code. When you need to make changes to the database, you'll write Ruby code, and then run "migrations" which makes the actual changes to the database.
Your solution from the original post looks like the best solution to me.
class Thing < ActiveRecord::Base
attr_reader :foo
def foo=(value)
@foo = ActiveRecord::ConnectionAdapters::Column.value_to_boolean(value)
end
end
If you wanted to clean things up a bit, you could always create a helper method that defines your foo=
writer method for you using value_to_boolean
.
I would probably create a module with a method called bool_attr_accessor
so you could simplify your model to look like this:
class Thing < ActiveRecord::Base
bool_attr_accessor :foo
end
It seems like ActiveModel ought provide something like this for us, so that virtual attributes act more like "real" (ActiveRecord-persisted) attributes. This type cast is essential whenever you have a boolean virtual attribute that gets submitted from a form.
Maybe we should submit a patch to Rails...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With