0

I have my model defined like this:

class Animal < ActiveRecord::Base
    mount_uploader :picture, PictureUploader

    attr_accessible :picture, :born_date, :father_id, :mother_id, :name, :obs, :earring, :animal_type, :animal_type_id, :inseminations

    validates :name, :born_date, :presence => true
    validates :earring, :presence => true, :if => :should_have_earring?

    belongs_to :father, :class_name => "Animal"
    belongs_to :mother, :class_name => "Animal"
    belongs_to :animal_type
    has_one :birth

    has_one :sell
    has_one :death

    has_many :inseminations
end

and

class Insemination < ActiveRecord::Base
  attr_accessible :bull_id, :cow_id, :done, :expected_birth_date, :expected_dry_date, :insemination_date, :obs, :rut

  validates :bull_id, :presence => true
  validates :cow_id, :presence => true
  validates :insemination_date, :presence => true

  belongs_to :bull, :class_name => "Animal"
  belongs_to :cow, :class_name => "Animal"

  has_one :birth
  has_one :abortion
  has_one :dry
end

Good, somewhere, I want to get the last insemination from some animal... so, I do @animal.inseminations.last, it should work, but, it does the select using a animal_id property, that does not exist in insemination model. So I get an error like this:

Mysql2::Error: Unknown column 'inseminations.animal_id' in 'where clause': SELECT inseminations.* FROM inseminations WHERE inseminations.animal_id = 1 ORDER BY inseminations.id DESC LIMIT 1

How can I specify it to searh in cow_id and/or bull_id columns? Is that possible?

Thanks in advance.

caarlos0
  • 20,020
  • 27
  • 85
  • 160
  • Did you tried using instances of Bull and Cow? Like `@bull = Bull.first`, `@bull.inseminations.last`. – MurifoX Sep 01 '12 at 14:20

2 Answers2

2

I think you have a few different options:

1) Instead of using has_many :inseminations, create two separate has many relationships:

has_many :cow_inseminations, :class_name => 'Insemination', :foreign_key => 'cow_id'
has_many :bull_inseminations, :class_name => 'Insemination', :foreign_key => 'bull_id'

2) Use STI and create subclasses of Animal. You will need to add a type field to Animal for this to work:

class Cow < Animal
  has_many :inseminations, :foreign_key => 'cow_id'
end

class Bull < Animal
  has_many :inseminations, :foreign_key => 'bull_id'
end

Then you can do Bull.first.inseminations or Cow.first.inseminations

Peter Brown
  • 50,956
  • 18
  • 113
  • 146
1

You can specify a foreign key:

has_many :inseminations, :foreign_key => :bull_id

However you can only have one foreign_key, so it doesn't work for the cows.

You can do something like Rails Model has_many with multiple foreign_keys to get it to work. But then in this case, you need:

has_many :bull_inseminations, :foreign_key => :bull_id
has_many :cow_inseminations, :foreign_key => :cow_id

def inseminations
  # not sure how you store animal type, but something like
  return bull_inseminations if animal_type == "bull"
  return cow_inseminations if animal_type == "cow"
end

For other attribute methods, you will need to do something similar if you want to use them, eg:

def inseminations_changed?
  bull_inseminations_changed? or cow_inseminations_changed?
end

and similarly with inseminations<<, inseminations=, etc.

Community
  • 1
  • 1
ronalchn
  • 12,225
  • 10
  • 51
  • 61
  • thanks... I tested the Beerlington first, because it's look more simpler, but I do believe that your should work too. Thanks. – caarlos0 Sep 01 '12 at 15:18