has_many/belongs_to relationship that doesn't use id


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



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


(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


(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>


<#User id: 75, login: blah>