Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type cast an ActiveRecord model virtual attribute

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

like image 228
Happynoff Avatar asked Jul 19 '12 12:07

Happynoff


People also ask

What is virtual attribute in Rails?

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).

What are ActiveRecord 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.

What's the purpose of ActiveRecord?

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 Ruby ActiveRecord?

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.


1 Answers

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...

like image 87
Tyler Rick Avatar answered Oct 13 '22 00:10

Tyler Rick