Re: Rails 4 RC1 polymorphic association not quite working.

73 views
Skip to first unread message
Message has been deleted

Art Mills

unread,
May 16, 2013, 8:11:26 AM5/16/13
to rubyonra...@googlegroups.com
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 :).
Reply all
Reply to author
Forward
0 new messages