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

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 => ‘. 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:ininitialize’
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

On Dec 22, 7:51 pm, “ed_ruder” [email protected] wrote:

set_table_name “pub_placement”
set_primary_key “preset_id”
set_sequence_name “pub_placement_assoc_seq”

idity!’
try next.

Thanks in advance.

Ed


Ryan R.
http://raaum.org
http://rails.raaum.org – Rails docs
http://locomotive.raaum.org – Self contained Rails for Mac OS X

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!