Search code examples
ruby-on-railsruby-on-rails-3ruby-on-rails-4ruby-on-rails-3.2ruby-on-rails-3.1

Multiple t.references get nil value for the second nested models


I have visits who belongs_to owner, and belongs_to car through two t.references, owner_id keeps getting nil when I create new visit through @car.visits.create.

Visit.rb

class Visit < ActiveRecord::Base
#validates :notes, presence:true
belongs_to :car
belongs_to :owner
end

Owner.rb

class Owner < ActiveRecord::Base
has_many :cars
has_many :visits    
accepts_nested_attributes_for :visits
accepts_nested_attributes_for :cars
end

Car.rb

class Car < ActiveRecord::Base
belongs_to :owner
has_many :visits
end

The migration for Visit

class CreateVisits < ActiveRecord::Migration
def change
create_table :visits do |t|
  t.boolean :open
  t.text :notes
  t.references :owner
  t.references :car
  t.timestamps null: false
end

end
end

if I

 car1 = Car.create(......)
 car1.visits.create(.....)

I get the value of Visit.owner_id = nil, however, car_id is perfectly filled with the right relation.

what am I missing? Help is much appreciated.

example from my console where owner_id: nil even when its created from a @car who has already owner_id


Solution

  • If my understanding is correct, your problem is that nowhere in your relations you enforce that owner_id in Car and owner_id in Visit should be the same. Your model would support a car belonging to one owner, but attached to a visit belonging to somebody else; so, when you create the visit, rails will leave owner_id to nil as it does not know to which owner that should belong.

    Three simple solutions:

    1. You can completely remove relation between Owner and Visit, and just create the methods you need, which would call the corresponding methods from Car:

      class Visit < ActiveRecord::Base
        belongs_to :car
      
        def owner_id
          car.owner_id
        end
      
        def owner
          car.owner
        end
      end
      
    2. Explicitly specify the owner in your create statement: car1.visits.create(owner: car1.owner, .....)

    3. Set owner_id to the correct value in a callback:

      class Visit < ActiveRecord::Base
        belongs_to :car
        belongs_to :owner
      
        before_create do
          self.owner_id = car.owner_id
        end
      end