views:

147

answers:

2

I'm having some issues with my code. This is probably due to some design fault. I've tried several things. Here are two.

Issue: I have a 1 (lending) - N (contracts) relation. I'd like to call lending.current_contract which would return the last relevant contract. Optimization is also an issue. I'd like to call :lending, :include => :contracts without having to use separate queries for contracts which are already in the contracts array containing all contracts.

Bad solution 1:

has_one :current_contract, :class_name => "Contract"

This doesn't work because every time I create, update or destroy it has to update the parent lending as well. Doing this I get a callback mess. For example when creating a lending, it also creates the first contract. For some reason going back and forth using callbacks for both the lending as its contract doesn't work.

Bad solution 2:

def current_contract
  return if contracts.relevant.empty?
  @current_contract = contracts.relevant.last
end

Sends a copy and not the reference. So lending.current_contract.status = value doesn't work.

Is there some design pattern which I should look at? And are there some examples? I've looked at some github projects but none of them had similar problems solved, therefore I think it is a design problem.

+2  A: 

Associations can generally take a :conditions hash, which can be handy. (And I'd forgotten this until I needed it about half an hour ago).

Would it help? Something like:

has_one :current_contract, :class_name => "Contract", :conditions => ...

Looking at the book a bit more (page 364 to be exact):

has_one :current_contract, :class_name => "Contract", :order => 'created_at DESC'

...which will reference the most recently-created contract. You may, of course, have a more suitable column.

I wish I'd seen that earlier - I need to go and change some code now...

Mike Woodhouse
A: 

By 'relevant', do you mean most recent?

class Lending < ActiveRecord::Base
  has_many :contract
  attr_reader :current_contract

  def initialize
   @current_contract = Contract.New
  end
  ...
end

class Contract < ActiveRecord::Base
  has_one :lending
  ...

  def before_delete
    # update lending to the most relevant contract
    # if this is the current_contract for parent lending
  end
end
iano