3

I was wondering if I can have a polymorphic association and also a presence validation

Let's say I have a business model and an address model, and address is polymorphic

class Business< ActiveRecord::Base
  has_one :address, as: :addressable
  validates_presence_of :address
end

class Address< ActiveRecord::Base
  belongs_to :addressable, polymorphic: true
end

Is it possible to have the validation validates_presence_of :address? I am having issues when creating objects with this setup.

Let's say first I create a business object like this

b = Business.new(name: "Hello23")
b.address = Address.new(street: "House 43 BCD")
b.save!

This doesn't work. It gives an undefined method constantize for 0:Fixnum and it makes sense to give an error, because when it tries to save the address to db it does not find an id of the addressable, since the business isn't yet saved and doesn't have an assigned id to it.

But it isn't possible from the other side around either - I can't save the business without having an address.

What is the best way to handle this kind of a situation?

****Apart from this what if I also want to have a validation on the address side like this**

validates_presence_of :addressable

I have been struggling with all this for about 2 days now. Let's see what ideas you people have ?**

nitsas
  • 972
  • 7
  • 17
Abid
  • 7,149
  • 9
  • 44
  • 51

2 Answers2

9

I think your problem has nothing to do with the validation code, which is ok either way.

Could i boldly suggest that you might have incorrectly set addressable_type column in the address db table to integer, not string :)

Viktor Trón
  • 8,774
  • 4
  • 45
  • 48
  • it wasn't the issue with the column type, but your confidence that the validation code is correct helped me think "What else could be wrong" which I finally figured out. thanks buddy – Abid May 21 '12 at 21:14
  • 2
    OMG you were damn right man.. Today after about a week of working on this code.. I was struck by another strange error only to realize that you were right I had mistakenly set addressable_type column in address table to integer not string. Just came back to leave this comment and thank you once again :). – Abid May 29 '12 at 12:51
1

Of course it is possible.

As for the object creation, this should work:

# controller.rb
@business = Business.new
@business.build_address

# view.erb
<%= form_for @business do |f| %>
  <%= f.fields_for :address do |address_form| %>
  ...
  <% end %>
<% end %>

See also Using build with a has_one association in rails.

Note: inside your model I'd recommend you to use new validation format:

class Business< ActiveRecord::Base
  has_one :address, as: => :addressable

  validates :address, :presence => true
end

Hope this will be helpful.

Community
  • 1
  • 1
melekes
  • 1,880
  • 2
  • 24
  • 30
  • I realized I was doing a lot wrong, the build method you wrote about hinted me to look into the right direction. I now have a much better understanding of how activerecord objects are built and saved. Thanks – Abid May 21 '12 at 21:13