Handling of relations belongs_to/has_many

Hi,

I'm fairly new to RoR and I think I don't get some of the ActiveRecord
magic.

I have:

# a lookup table (used to show countries in a <select>)
class Country < ActiveRecord::Base
  has_many :breeders
  validates_presence_of :name
end

# a table of companies (each located in a specific country).
class Breeder < ActiveRecord::Base
  belongs_to :country
  validates_presence_of :name
  validates_associated :country # may be NIL when we don't know it yet
end

Currently, I do in the controller to create or update a Breeder:

  def create
    p=params[:breeder]
    country_id = p[:country_id]
    @breeder = Breeder.new(p)
    @breeder.country = country_id.blank? ? nil :
Country.find(country_id)
    if @breeder.save
    ....

What exactly is the difference for @breeder.country when it's assigned
a (found) Country or breeder.country_id is set by
Breeder.new(params[:breeder]) ?

Both save the country_id to the "breeders" table; besides that, the
Breeder "knows" that the country_id (may) refer to a country and could
do the find above itself.

Regards,

Thomas

Currently, I do in the controller to create or update a Breeder:

  def create
    p=params[:breeder]
    country_id = p[:country_id]
    @breeder = Breeder.new(p)
    @breeder.country = country_id.blank? ? nil :
Country.find(country_id)
    if @breeder.save
    ....

What exactly is the difference for @breeder.country when it's assigned
a (found) Country or breeder.country_id is set by
Breeder.new(params[:breeder]) ?

There is no difference, except that your controller code gets
unneccessarily verbose.

The following should work just fine:

  def create
     @breeder = Breeder.new(params[:breeder])
     if @breeder.save

Much simpler.

AR lazily initialises the breeder.country field on first access and
internally performs a Country.find(breeder.country_id). Conversely, if
you set the country field, country_id is updated.

In short, don't bother with finding and setting the country yourself.

Cheers,
Max

Max,

The easiest workaround would be to validate yourself.

class SomeModel
  def validate
    errors.add 'some_attribute', 'cannot be blank' unless self.some_attribute
  end
end

Cheers,
Max