I have this question up at Stack Overflow and am hoping I am just not
quite
right. I’ve gotten polymorphic associations working in Rails 3.2.X but
for some reason in 4.0 I’m just missing something. Currently the code
I’ll attach does most everything right. But it fails to capture the
addressable_id even though in the log I see that ID is correct and it
looks
like it is being committed. My guess is I have something wrong with
how
I’m doing the view, or something slightly wrong in the business
controller.
I’m hoping someone can jar me toward the solution. This is a simple
address model that will be used in a number of other models.
Any help is appreciated. The problem pasted below states I get “two”
addresses, one blank, and one that has the params, but not
addressable_id.
If I remove from create and update the @address =
@business.create_address(params[:address]) I only get one, so it seems
having both invokes the build to save and the create to be saved with
one
being totally nil and the other not having an addressable type.
THIRD UPDATE: Ok, now I am very close, I think. I now am creating data
and the parameters are being set in the DB. I changed the business
controller strong params to be:
def business_params
params.require(:business).permit(:name, :description,
:address_attributes=>[:line1, :line2, :city, :state, :zip])
When I edit an existing business I get TWO addresses created for some
reason. One is empty and one is complete with the parameters. So, I
think I’m very close if anyone has the final push :).
Address model
class Address < ActiveRecord::Base
belongs_to :addressable, polymorphic: true
end
Business model:
class Business < ActiveRecord::Base
#each business belongs to user, through user_id
belongs_to :owner
has_one :address, as: :addressable
accepts_nested_attributes_for :address
# each business has many customers and has many services
has_many :customers
has_many :services
validates :owner_id, presence:true
validates_presence_of :name
#validates_length_of :state, is: 2
end
business controller:
class BusinessesController < ApplicationController
before_action :get_owner
before_action :set_business, only: [:show, :edit, :update,
:destroy]
#helper_method :sort_column, :sort_direction
def index
@businesses = @owner.businesses
end
def show
#@customer = @business.customers.order(sort_column + " " +
sort_direction)
end
def new
@owner = Owner.find(params[:owner_id])
@business = @owner.businesses.build
@address = @business.build_address(params[:address])
end
def edit
@address = @business.build_address(params[:address])
end
def create
@business = @owner.businesses.new(business_params)
@address = @business.create_address(params[:address])
respond_to do |format|
if @business.save
format.html { redirect_to owner_businesses_url(@owner),
notice:
‘Business was successfully created.’ }
format.json { render action: ‘show’, status: :created,
location: @business }
else
format.html { render action: ‘new’ }
format.json { render json: @business.errors, status:
:unprocessable_entity }
end
end
end
def update
@address = @business.create_address(params[:address])
respond_to do |format|
if @business.update(business_params)
format.html { redirect_to owner_businesses_url(@owner),
notice:
‘Business was successfully updated.’ }
format.json { head :no_content }
else
format.html { render action: ‘edit’ }
format.json { render json: @business.errors, status:
:unprocessable_entity }
end
end
end
def destroy
@business.destroy
respond_to do |format|
format.html { redirect_to owner_businesses_url(@owner) }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between
actions.
def set_business
@business = @owner.businesses.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the
white list through.
def business_params
params.require(:business).permit(:name, :description,
:address_attributes=>[:line1, :line2, :city, :state, :zip])
end
def get_owner
@owner = Owner.find(params[:owner_id])
end
#def sort_column
# Customer.column_names.include?(params[:sort]) ? params[:sort]
:
“first_name”
#end
#def sort_direction
# %w[asc desc].include?(params[:direction]) ?
params[:direction] :
“asc”
#end
end
form view:
<%= form_for([@owner, @business]) do |f| %>
<% if @business.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@business.errors.count, "error") %>
prohibited this business from being saved:
<ul>
<% @business.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :description %><br />
<%= f.text_area :description %>
</div>
<%= f.fields_for :address do |address| %>
<%= p address.object %>
<div class="field">
<%= address.label :line1 %><br>
<%= address.text_field :line1 %>
</div>
<div class="field">
<%= address.label :line2 %><br>
<%= address.text_field :line2 %>
</div>
<div class="field">
<%= address.label :city %><br>
<%= address.text_field :city %>
</div>
<div class="field">
<%= address.label :state %><br>
<%= address.text_field :state %>
</div>
<div class="field">
<%= address.label :zip %><br>
<%= address.number_field :zip %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Now I’m getting two addresses created. One empty, one with the
parameters
set. Almost there :).