Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

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
    self.title.parameterize('_').to_sym
  end
end


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
end

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
end

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!

share|improve this question

1 Answer 1

up vote 3 down vote accepted
+50

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.

share|improve this answer
    
Thanks... I'll give this a try. I especially like the idea of using the after_save callback to avoid server restarts. –  Jason Lewis Jan 16 '12 at 5:48
    
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! –  Jason Lewis Jan 17 '12 at 14:16

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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