Trying to get has_many :through working with legacy tables

My first significant Rails app needs to integrate with a legacy database and I'm having trouble getting my has_many :through relationship working. (I've tried a number of permutations to what I describe below and I've searched through this group's archives and Googled for clues, but I haven't figured out what I'm doing wrong.)

The legacy tables don't follow RoR conventions, so I'm specifying table names, primary keys and sequence names explicitly (running on Oracle) and turning off pluralization of table names--that part seems to work. (I can Model#find individual records in the tables.)

Since all of the legacy tables don't pluralize table names, I sub-classed ActiveRecord::Base like this:

class MyActiveRecord < ActiveRecord::Base   self.pluralize_table_names = false end

Each of my models inherit from the MyActiveRecord. Here they are:

class PubPlacement < MyActiveRecord   set_table_name "pub_placement"   set_primary_key "placement_id"   set_sequence_name "pub_placement_seq"

  has_many :pub_placement_assocs   has_many :pub_presets, :through => :pub_placement_assocs, :source => :preset_id end

class PubPreset < MyActiveRecord   set_table_name "pub_preset"   set_primary_key "preset_id"   set_sequence_name "domain_preset_seq"

  has_many :pub_placement_assocs   has_many :pub_placements, :through => :pub_placement_assocs, :source => :placement_id end

class PubPlacementAssoc < MyActiveRecord   set_table_name "pub_placement_assoc"   set_primary_key "assoc_id"   set_sequence_name "pub_placement_assoc_seq"

  belongs_to :pub_placement, :foreign_key => "placement_id"   belongs_to :pub_preset, :foreign_key => "preset_id" end

In script/console, I can find individual records from each of these tables successfully. However, when I try something like this (return values filtered):

p = PubPlacement.find 64

  <legit pub_placement object>

p.pub_presets

I get this result:

ActiveRecord::HasManyThroughSourceAssociationNotFoundError: Could not find the source association(s) :preset_id in model PubPlacementAssoc. Try 'has_many :pub_presets, :through => :pub_placement_assocs, :source => <name>'. Is it one of :stuck_out_tongue: ub_placement or :pub_preset?         from ./script/../config/../config/../vendor/rails/activerecord/lib/active_record/reflection.rb:173:in `check_val idity!'         from ./script/../config/../config/../vendor/rails/activerecord/lib/active_record/associations/has_many_through_a ssociation.rb:6:in `initialize'         from ./script/../config/../config/../vendor/rails/activerecord/lib/active_record/associations.rb:920:in `pub_pre sets'         from (irb):2

I've been staring this in the face for a while and don't know what to try next.

Thanks in advance.

Ed

Hi Ed,

I haven't worked through your exact situation, but my current guess is that you need some

  :class_name => "PubPreset"

or the like in your associations here and there... (or not, but probably worth trying.. :slight_smile:

Best,

-r

I poked around a bit more and figured out that I made several mistakes in my models. Here's a simplification of the has_many :through models that work (the sequence stuff is irrelevant):

class PubPlacement < MyActiveRecord   set_table_name "pub_placement"   set_primary_key "placement_id"

  has_many :pub_placement_assocs, :foreign_key => :placement_id   has_many :pub_presets, :through => :pub_placement_assocs end

class PubPreset < MyActiveRecord   set_table_name "pub_preset"   set_primary_key "preset_id"

  has_many :pub_placement_assocs, :foreign_key => :preset_id   has_many :pub_placements, :through => :pub_placement_assocs

class PubPlacementAssoc < MyActiveRecord   set_table_name "pub_placement_assoc"   set_primary_key "assoc_id"

  belongs_to :pub_placement, :foreign_key => :placement_id   belongs_to :pub_preset, :foreign_key => :preset_id end

I learned:

- belongs_to and has_many require :foreign_key to be specified if Rails naming conventions for the foreign keys aren't followed - the :source parameter for has_many :through relationships specifies the name of an association in the join table (not a foreign key name), and you don't need it if the association name follows Rails naming conventions (e.g., "has_many :pub_placements, :through => :pub_placement_assocs" doesn't need the :source parameter if the association in the join table is named ":pub_placement" or ":pub_placements")

Thanks!