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:</h2> <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 :). -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/6cc3544b-deb2-44d0-ab2d-c70c8a6d9d57%40googlegroups.com?hl=en-US. For more options, visit https://groups.google.com/groups/opt_out.
Art Mills
2013-May-16 12:11 UTC
Re: Rails 4 RC1 polymorphic association not quite working.
As an update to this, if I remove the @address = @business.create_address(params[:address]) from create and update only one record is created. However, it is being created with an addressable_id of NIL even though I see it inserting with the right addressable_id in the log. I figured maybe I''m doing something wrong as this is a nested group so I made the same code in a simple model and it "works" I think. Meaning, I can create and edit an address and it shows on my form if in the edit I change it to, in the case of my simple test: @address = @article.address ||= @article.create_address(params[:address]) But when I update that address, it creates another address instead of updating the existing one, leaving the existing one as an addressable_id of NIL in the database. I think I must be closing in on this one :). On Wednesday, May 15, 2013 7:05:48 AM UTC-5, Art Mills wrote:> > 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:</h2> > > <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 :). >-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/ac4329ff-d69d-46eb-9588-714e3e1baadf%40googlegroups.com?hl=en-US. For more options, visit https://groups.google.com/groups/opt_out.