gianpi
gianpi

Reputation: 3210

Rails 3.2 + Postgres: has_and_belongs_to_many saving even when validation fails

I have a Company model:

class Company < ActiveRecord::Base
    has_and_belongs_to_many :jobs
    validates :name, presence: true
end

And a Job model:

class Job < ActiveRecord::Base
    has_and_belongs_to_many :companies
    validates :name, presence: true
end

All works fine except for the collection.create method. According to the Rails documentation:

The collection.create method returns a new object of the associated type. This object will be instantiated from the passed attributes, the link through the join table will be created, and, once it passes all of the validations specified on the associated model, the associated object will be saved.

This doesn't seem to work properly for me: even when the child object is invalid (and the validation works because the invalid model doesn't get saved), the association still gets created. I created this unit test to explain how I try to do it:

test "add invalid job to company" do
  company = FactoryGirl.create(:company_with_job)

  # I also tried:
  # company.jobs << FactoryGirl.build(:job, name: "")
  company.jobs.create({name: ""})
  company.save
  assert_equal 1, company.jobs.size
end

Size is instead '2' and if I inspect company.jobs I get this:

[#<Job id: 1, name: "My Job 1", created_at: "2012-11-07 10:26:10", updated_at: "2012-11-07 10:26:10">, 
#<Job id: nil, name: "", created_at: nil, updated_at: nil>]

I'm sure I'm missing something stupid, but I've been banging my head on this for a while and can't seem to understand what I'm doing wrong.

Thanks,
g

Upvotes: 0

Views: 601

Answers (1)

apneadiving
apneadiving

Reputation: 115541

company.jobs actually contains two jobs, but one is persisted while the invalid is not.

You could test:

  • company.jobs.select(&:persisted?).size

  • company.reload.jobs.size

Upvotes: 1

Related Questions