HiveBrain v1.2.0
Get Started
← Back to all entries
patternrubyrailsMinor

Dynamic association generation in ActiveRecord

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
activerecordgenerationassociationdynamic

Problem

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  :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!

Solution

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.

Code Snippets

config.log_level = :debug

Context

StackExchange Code Review Q#7682, answer score: 4

Revisions (0)

No revisions yet.