I am trying to make an app in Rails 4.
I have a profile model and an address model.
the Associations are:
profile.rb
has_many :addresses, as: :addressable
address.rb
belongs_to :addressable, :polymorphic => true
Address is a polymorphic model.
I have an address form which has:
<%= simple_form_for(@address) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<div class="row">
<div class="col-xs-3">
<%= f.input :unit %>
</div>
<div class="col-xs-3 col-xs-offset-1">
<%= f.input :street_number %>
</div>
<div class="col-xs-3 col-xs-offset-1">
<%= f.input :street %>
</div>
</div>
<div class="row">
<div class="col-xs-3">
<%= f.input :building %>
</div>
<div class="col-xs-3 col-xs-offset-1">
<%= f.input :city %>
</div>
<div class="col-xs-3 col-xs-offset-1">
<%= f.input :region %>
</div>
</div>
<div class="row">
<div class="col-xs-3">
<%= f.input :zip %>
</div>
<div class="col-xs-3 col-xs-offset-1">
<%= f.input :country, priority: [ "Australia", "New Zealand", "United Kingdom" ] %>
</div>
</div>
<div class="row">
<div class="col-xs-3">
<%= f.input :main_address %>
</div>
<div class="col-xs-3 col-xs-offset-1">
<%= f.input :project_offsite %>
</div>
</div>
</div>
<div class="form-actions">
<%= f.button :submit, :class => "formsubmit" %>
</div>
<% end %>
I try to create an address and save it. I then check that it is in the rails console. Something is going wrong because the rails console shows this:
#<Address id: 1, unit: "", building: "", street_number: "34", street: "f", city: "sdfasdf", region: "asdf", zip: "2000", country: "GB", main_address: nil, project_offsite: nil, time_zone: nil, latitude: nil, longitude: nil, addressable_id: nil, addressable_type: nil, created_at: "2015-12-30 00:07:00", updated_at: "2015-12-30 00:17:00">
The addressable id and the addressable type are both nil.
They should have the references back to profile or wherever the related model is.
Is there a step missing in setting up this process?
This video (minute 3.40) says rails automatically handles filling out the type and id fields for polymorphic models. https://gorails.com/episodes/comments-with-polymorphic-associations?autoplay=1
When I try to create a new address from the rails console, I type:
Address.create(addressable: Address.first, profile_id: "1", country: "AU")
The console error is:
ActiveRecord::UnknownAttributeError: unknown attribute 'profile_id' for Address
My address table has an addressable_id key and my profile model has has_many :addresses, as: :addressable
I can't understand what causes the error
ANOTHER ATTEMPT
So, from what I gather from the suggestions below, I need to do something to let address know that it belongs to a profile.
I also found this article which sets out an example of what needs to happen in the profiles controller to get things working with polymorphic associations: http://6ftdan.com/allyourdev/2015/02/10/rails-polymorphic-models/
I change my new action in the profiles controller to (include addresses.build):
def new
@profile = Profile.new
@profile.qualifications.build
@profile.visions.build
@profile.personalities.build
@profile.addresses.build
authorize @profile
end
I add nested attributes to my address association in the profile model:
has_many :addresses, as: :addressable
accepts_nested_attributes_for :addresses, reject_if: :all_blank, allow_destroy: true
I change my address form: - from form_for to fields_for; - rename it _address_fields.html.erb; and - open the div tag with:
<div class="nested-fields">
In my profiles form, I add the link to the form partial:
Your addresss
</div>
<%= f.simple_fields_for :addresses do |f| %>
<%= render 'addresses/address_fields', f: f %>
<% end %>
</div>
<div class="row">
<div class="col-md-6">
<%= link_to_add_association 'Add an address', f, :addresses, partial: 'addresses/address_fields' %>
</div>
All of this is as set out in Jeiwan's answer on this post: Rails - Cocoon gem - Nested Forms
Then, when I try all of this, I get this error:
ActiveRecord::RecordNotUnique in ProfilesController#update
PG::UniqueViolation: ERROR: duplicate key value violates unique constraint "index_addresses_on_addressable_type_and_addressable_id" DETAIL: Key (addressable_type, addressable_id)=(0, 1) already exists. : INSERT INTO "addresses" ("unit", "building", "street_number", "street", "city", "region", "zip", "country", "addressable_id", "addressable_type", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) RETURNING "id"
The error points to the update method in the profiles controller:
def update
respond_to do |format|
if @profile.update(profile_params)
format.html { redirect_to @profile }
format.json { render :show, status: :ok, location: @profile }
else
I found this post which describes a user's similar problem, but before i change the database, I'd like to try and understand what has happened.
Rails auto-assigning id that already exists
Another odd thing is when I look at the last address created in the console, it shows this:
#<Address id: 6, unit: "", building: "", street_number: "34", street: "asdf", city: "asdf", region: "add", zip: "2111", country: "AU", main_address: nil, project_offsite: nil, time_zone: nil, latitude: nil, longitude: nil, addressable_id: 1, addressable_type: 0, created_at: "2016-01-01 22:01:31", updated_at: "2016-01-01 22:01:31">]>
The record now has an addressable_id but does not have an addressable_type. Is there something extra required to populate this field?