views:

96

answers:

4

I've got a table that includes a column named "valid". This has caused a problem after updating to Rails 2. ActiveRecord is expecting "def valid?" to do validation, not return a boolean value from the database.

How do I work around this problem? Is renaming the column my only option?

A: 

I can prevent the crash by adding the following to my model, but it's not entirely satisfactory:

class << self
  def instance_method_already_implemented?(method_name)
    return true if method_name == 'valid?'
    super
  end
end
Terry Lorber
A: 

Do you need to see the column in your model? If not, overriding ActiveRecord::Base.columns will do the trick...

def self.columns
  super.delete_if {|c| c.name == 'valid' }
end
casey
A: 

You can access the attribute through the [] notation:

row[:valid] = "foo"

You'll get the DangerousAttributeError if you try to initialize an object like this:

row = MyModel.new :valid => "foo"

To prevent that, you can define an attribute setter for valid, like this:

def valid=(x)
  self[:valid] = x
end

The valid? method will still be for row validation. You could define a different question method, like val? to get at the boolean, like this:

def val?
  query_attribute('valid')
end

Now you can use row.val? to test the boolean

showaltb
+3  A: 

As documented elsewhere, there are things you can do, but I'm going to suggest that they're probably going to be more trouble in the long run than biting the bullet and renaming the column.

If your database is not open to other apps, that is - otherwise you're just going to suffer to some extent whatever you do...

Why rename? One of the greatest benefits that we get from Rails is convention over configuration. The "magic", if you will. (Some say that it's actually a bad thing, but go with me one this). If you retain a column named "valid", then nyou're making your models inconsistent: this one needs to work differently from the others and that's bad. Or you could monkey-patch ActiveRecord::Base perhaps, so then all your models work the same but your app no longer follows convention.

From personal experience: I created a column named "user_id" which ActiveRecord, by convention, considered a foreign key (as it does anything ending in "_id"). I coded around it, which I now think was a mistake. Another item on the to-do list...

It's not necessarily wrong to go against Rails conventions: there are plenty of places where you can do so and they're well-documented. On the ActiveRecord side, many are specifically designed to reduce difficulty in connecting to legacy database schemas, for example. Take a good look at the pros and cons, as you're obviously doing, and weigh up your options.

Mike Woodhouse
I did that on my first rails app. I had a column (or maybe it was a table) named "image" and I renamed it as soon as I figured out why my app was busted.
Andy Gaskell
Agreed, rename the column. This will cause less confusion in the long run. If I see "model.valid" I assume it has something to do with Rails validations (not an attribute like in this case).
ryanb
I agree, power through convention. However, I'm using my hack until I can schedule a change with my dependents.
Terry Lorber