I'm developing a Rails-based web interface/API for a large, vendor-supplied, legacy Oracle database. One of the constraints is that I can't change the schema other than adding views, because it still has to support the vendor's application.

The table for customer data has a limited number of columns, and extended attributes are stored in customer_def_field_value. These attributes are defined in customer_def_field_def.

so I end up with the classes:

class FieldDef < ActiveRecord::Base

  set_table_name 'customer_def_field_def'
  set_primary_key :customer_def_field_def_id
  set_sequence_name 's_customer_def_field_def'

  alias_attribute :field_def_id, :customer_def_field_def_id

  has_many :field_values

  def symbol

class FieldValue < ActiveRecord::Base

  set_table_name 'customer_def_field_value'
  set_primary_keys :cust_id, :customer_def_field_def_id
  set_sequence_name :autogenerated

  alias_attribute :field_def_id, :customer_def_field_def_id

  belongs_to :customer, :foreign_key => :cust_id
  belongs_to :field_def, :foreign_key => :customer_def_field_def_id

In order to get associations on Customer for each of the 'custom fields', I have this code in the Customer class:

FieldDef.find_each do |field|
  has_one field.symbol, :class_name => 'FieldValue', :foreign_key => :cust_id, :conditions => proc{ "customer_def_field_def_id = #{field.id}"}
  accepts_nested_attributes_for field.symbol
  delegate :field_value, :to => field.symbol, :prefix => true
  delegate :field_value=, :to => field.symbol, :prefix => true
  attr_accessor ('set_' + field.symbol.to_s).to_sym

This works like a charm, but it queries the DB every time a Customer is instantiated in order to generate the method definitions.

It hasn't been a performance issue... yet.

New custom field types aren't added very often, so I think I might be able to do this in an initializer rather than in my model, and just restart the application if new fields have to be added... but I wanted to get some feedback. Thanks!


1 Answer 1


I think the query of the database would only happen once in production mode (the class would get cached, in development mode, the class gets reloaded every request that references a Customer object). You can confirm this by setting:

config.log_level = :debug

in your production.rb file and seeing if the query runs more than once. It might be worth having an after_save callback for FieldDef that does the same thing as the "FieldDef.find_each do |field|" block you have so you don't have to restart the server when new FieldDefs are created.

  • \$\begingroup\$ Thanks... I'll give this a try. I especially like the idea of using the after_save callback to avoid server restarts. \$\endgroup\$ Commented Jan 16, 2012 at 5:48
  • \$\begingroup\$ You're absolutely right. The query to generate the associations is only run the first time, when the class is cached. Sadly, the after_save callback won't save me from restarting periodically, as new custom fields are usually added from the vendor's application. Thanks! \$\endgroup\$ Commented Jan 17, 2012 at 14:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.