views:

87

answers:

2

I have the following

class Item < ActiveRecord::Base
end

class Talk < Item
end

with the migration

class CreateItems < ActiveRecord::Migration
  def self.up
    create_table :items do |t|
      t.string :type
      t.string :name
      t.text :description
      t.time :start_time
      t.time :duration
      t.timestamps
    end
  end

  ...
end

By default the description property will be available on the Item and Talk classes. Is there a way to restrict the property so that is only available to the Talk class?

A: 

I do not think that it is possible to restrict/remove a property.

You can hide the property (a bit) by undefining the getter and setter methods. Add is to some exclude option in order to make sure it is not fetched from the database by default. But this is only hiding, since the field always is present in the database and can be fetched manually.

But why do you want to hide the property? If you just do not use it then it does not matter to leave it in the Item class. If you want to save space, because it is rarely used, then you could split the Item table into an Item and a ItemDescription table and use a has_one relation. In that case it is only fetched when there is indeed a ItemDescription available for the Item you are handling.

Veger
+1  A: 
class Item < ActiveRecord::Base
  def duration
    raise NoMethodError
  end

  def duration=(value)
    raise NoMethodError
  end
end

class Talk < Item
  def duration
    read_attribute(:duration)
  end

  def duration=(value)
    write_attribute(:duration, value)
  end
end

You could always do that, but it's a lot of work for nothing. What's the worst that will happen when you read duration on an Item? You'll get back nil, which will cause a crash shortly thereafter. You don't need to be so concerned about these types of issues in Ruby.

If needed, you can create a module and include the module in the two classes, for the shared behavior, and drop the STI.

François Beausoleil
The property is still readable in the Item class using `read_attribute(:duration)`... Also putting it in a module does not seem to help since the ActiveRecord 'magically' finds the properties, not the self-written classes.
Veger
Perhaps this is a case of my java day job influencing me. My thinking is that without protecting the property another developer might expect the field to be in use where in fact it isn't. For instance they might create a view that references the description field. Of course on my current rails project there is in fact only 2 of us and we obviously communicate enough for this not to happen. It does leave me with a niggling feeling though, ah well :)
opsb