Question

I have two ActiveRecord models with a hasMany / belongsTo association:

class User < ActiveRecord::Base
  has_many :letters
end

class Letter < ActiveRecord::Base
  belongs_to :user
end

The User model has a revision_number attribute, to which I would like to scope the belongs_to association, so the letter is associated to a User by both user.id and user.revision_number.

I tried using the :conditions key as documented in the API docs:

class Letter < ActiveRecord::Base
  belongs_to :user, :conditions => "revision_number = #{client_revision}"
end

but this attempts to call client-revision on the Letter class, not the instance of Letter. Could anyone point me in the right direction for scoping the belongs_to association correctly?

I'm using the acts-as-revisable plugin to version the User model.

Was it helpful?

Solution 2

Finally figured out what I needed was something like composite keys, which Rails ActiveRecord doesn't support. The solution (for now at least) was to write custom client accessors on the Letter to support the composite keys (id and revision_number):

class Letter < ActiveRecord::Base
  def client
    Client.find_by_id(self.client_id).try(:find_revision, self.client_revision)
  end

  def client=(c)
    self.client_id = c.id
    self.client_revision = c.revision_number
  end
end

class Client < ActiveRecord::Base
  acts_as_revisable

  has_many :letters
end

With this setup, Client#1.letters will retrieve an array of both letters, but Letter#2.client will retrieve Client#1r2, whilst Letter#2.client will retrieve Client#1r4:

Client         id:    1    1    1    1    1    1
       rev_number:    1    2    3    4    5    6

Letter         id:         1              2
        client_id:         1              1
  client_revision:         2              5

Still not sure if this is the best approach to this problem, but it seems to work for now.

OTHER TIPS

I am having a hard time understanding why you would want to scope the belongs_to in this way. Correct me if I am wrong, but it might be better to do something like this. I am assuming you want some sort of version control system:

class User < ActiveRecord::Base
  has_many :letters
end

class Letter < ActiveRecord::Base
  has_many :revisions, :class_name => "LetterVersion"
  belongs_to :current, :class_name => "LetterVersion"
end

class LetterVersion < ActiveRecord::Base
  belongs_to :letter
end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top