has_many/belongs_to relationship that doesn't use id

Hi,

Banging by head against a wall here, and i'm sure this is easy

I have a table called channel_statistics and one called installations

in both there is a column called node_identifier

I want to be able to do

ChannelStatistic.find(:all, :include => [:installations]) as this has
a lot of data in it I want to eager load

so i have tried

class ChannelStatistic < ActiveRecord::Base

  belongs_to :installation, :foreign_key => 'node_identifier'

...
end

class Installation < ActiveRecord::Base

   has_many :channel_statistics, :foreign_key => 'node_identifier'

....
end

but to no avail.

It always performs the "LEFT OUTER JOIN on installations.id =
channel_statistics.node_identifier"

What I want it to do is "LEFT OUTER JOIN on
installations.node_identifier = channel_statistics.node_identifier"

Guess they might not be able to handle this but it seems unlikely
somehow!
Possibility that with_scope might help but I have never got that
working how I want either

Please help!!

Thanks

Joe

So you want to define all channel statistics that belong to an installation and all installations that belong to a channel statistic? This sounds like a has and belongs to many, or has_many through problem :slight_smile:

The association just needs to work with both keys being named
node_identifier
It can't use the normal rails _id convention because the stats get
dumped by a separate app and i am not able to perform a lookup on the
node_identifier to find the installation_id before each stats update
(would create too much db activity)

So the question is simply, how do i override rails's usually magic
presets and create an assocation between the two tables which uses the
node_identifier column in both tables as the join.

There is only ever one installation per channel statistic so it is not
a HABTM problem

THanks again!

I'm going to answer my own question because I'm sure I'm not alone
with this problem

The solution I came up with was to subclass the main ActiveRecord
model and override the primary key and relationships in there

e.g.

(Main Model Class)
class Installation < ActiveRecord::Base
    #...some normal relationships here
end

(subclassed)
class InstallationStatistic < Installation

    set_primary_key 'node_identifier'

    has_many :channel_statistics, :foreign_key => 'node_identifier'

   def save
       do_not_save_and_warn
   end
   alias_method :save!, :save
   alias_method :create, :save
   alias_method :create!, :save
   alias_method :<<, :save

   private
   def do_not_save_and_warn
        logger.warn("Can't save with this model for association only.
Instantiate Installation instead.")
   end

end

(association)
class ChannelStatistic < ActiveRecord::Base
     belongs_to :installation, :class_name =>
'InstallationStatistic, :foreign_key => 'node_identifier'
end

This seems to allow me to maintain my relationships with Installation
and its other relationships, while creating a new one based on a
different primary key. I have overridden the save methods so that we
don't mess up the installation table or try and create a subclassed
entry.

Now i can do

channel_statistic = ChannelStatistic.find(:first)
channel_statistic.installation

<#IInstallationStatistic id: 54, node_identifier: blah, :user_id: 75>

channel_statistic.installation.user

<#User id: 75, login: blah>

Great!!