9

After upgrading from Rails 3.2 to 4.1, the following code which used to work is now failing:

in a controller/spec:

post = user.posts.build
post.contacts << contact # contact is a persisted record
post.save! # now fails

I'm basically trying to save the post along with its associated contact, which is supposed to create a contact_publishment record on-the-fly. The error is on the new contact_publishment record: "Publishable can't be blank"

the model:

class Contact
  ...
  has_many :contact_publishments
  ...
end

class ContactPublishment
  ...
  belongs_to :publishable, polymorphic: true
  belongs_to :contact
  validates_uniqueness_of :publishable_id, :scope => [:contact_id, :publishable_type]
  validates_presence_of :contact, :publishable
  ...
end

class Post
  ...
  has_many :contact_publishments, as: :publishable
  has_many :contacts, through: :contact_publishments
  ...
end
Antony Mithun
  • 161
  • 1
  • 15
Yossi Shasho
  • 3,632
  • 31
  • 47

2 Answers2

10

In Rails 3.2 owner model has been saved before perform validation nested association, in 4.1 validation before model saved, and because post not saved, validation

class ContactPublishment
    validates_presence_of :publishable

does not allow to pass validation (post not saved in db)

For resolve this, you may disable validation in Post model, (validation on ContactPublishment has been called from Contact model)

class Post < ActiveRecord::Base
      has_many :contact_publishments, as: :publishable, validate: false

or replace presence validation like this:

class ContactPublishment < ActiveRecord::Base
  validates_associated :publishable

change_column :contact_publishments, :publishable_type, :string, null: false
change_column :contact_publishments, :publishable_id, :integer, null: false

or do it through proxy_association

Vakiliy
  • 871
  • 6
  • 12
  • Thank you! it worked! except for the `change_table` commands, which i had to change to `change_column`. Big thank you, i was stuck on this for a few days. – Yossi Shasho Jun 04 '14 at 14:57
  • Of course, it would be correct change_column, when he wrote, thought about ALTER TABLE. Thank you! – Vakiliy Jun 04 '14 at 15:28
  • Wow, this is a really strange thing for them to change in Rails... :P – Taryn East Aug 25 '14 at 01:29
1

I think the association is not updating because you do not have inverse_of setup between contact and contact_publishment.

From the docs about setting up a :through

If you are going to modify the association (rather than just read from it), then it is a good idea to set the :inverse_of option on the source association on the join model. This allows associated records to be built which will automatically create the appropriate join model records when they are saved.

  • 1
    Tried it and it didn't work. Regardless, the problem is not with the `contact`, but with the `contact_publishment` and the `post`. Moreover, `inverse_of` doesn't work with polymorphic associations so it will not work in the case of the `post` – Yossi Shasho Jun 04 '14 at 14:45