title: Rails 5 - using polymorphic associations - rendering the views
body: <p>I'm trying to learn how to use polymorphic associations in my Rails 5 app.  I recently asked <a href="https://stackoverflow.com/questions/40455139/rails-polymorphic-association-rendering-associated-instances-only">this</a> question, but I edited it so many times to show all the things I was trying, it has become messy</p>
  
  <p>I have models called Organisation, Proposal and Package::Bip.</p>
  
  <p>The associations are:</p>
  
  <p>Organisation</p>
  
  <pre><code>has_many :bips, as: :ipable, class_name: Package::Bip
      accepts_nested_attributes_for :bips,  reject_if: :all_blank, allow_destroy: true
  </code></pre>
  
  <p>Proposal</p>
  
  <pre><code>has_many :bips, as: :ipable, class_name: Package::Bip
      accepts_nested_attributes_for :bips,  reject_if: :all_blank, allow_destroy: true
  </code></pre>
  
  <p>Package::Bip</p>
  
  <pre><code>belongs_to :ipable, :polymorphic =&gt; true, optional: true #, inverse_of: :bip
  </code></pre>
  
  <p>Package::Bip can be associated with either of Organisation or Proposal. I'm struggling to figure out how to show the Package::Bips that only belong to proposal in my proposal show and the same for organisation.</p>
  
  <p>My package::bip table has these 2 columns:</p>
  
  <pre><code>#  ipable_id      :integer
  #  ipable_type    :string
  </code></pre>
  
  <p>The ipable_type gets set to either Proposal or Organisation.</p>
  
  <p>In my proposal show, I have:</p>
  
  <pre><code>&lt;% if @proposal.bips.present? %&gt;
      &lt;%#= render @proposal.bips %&gt;
       &lt;%= link_to proposal_package_bips_path(@proposal) do %&gt; 
       &lt;% end %&gt;
  &lt;% end %&gt;
  </code></pre>
  
  <p>I found <a href="http://www.codequizzes.com/rails/learn-rails/polymorphism" rel="nofollow noreferrer">this</a> post. I understand it to mean I should also be able to try this: I have also tried:</p>
  
  <pre><code>&lt;% if @proposal.bips.present? %&gt;
      &lt;%= render @proposal.bips %&gt;
  &lt;% end %&gt;
  </code></pre>
  
  <p>I think the (@proposal) should be the constraining factor in deciding which package_bip instances to return. But, it isn't. I'm not sure what it's doing because all package_bips get rendered (including those that are associated with an organisation).</p>
  
  <p>In my proposal controller, I have:</p>
  
  <pre><code> def index
      @proposals = Proposal.all
      # @bips = @proposal.bips
      # authorize @proposals
    end
  
  
  def show
      @bips = @proposal.bips#.where(ipable_type: 'Proposal')
  end
  </code></pre>
  
  <p>In my Package::BipsController, I have</p>
  
  <pre><code>def index
  
      if params[:ipable_type] == "Proposal"
        @bips = Package::Bip.where(:ipable_type == 'Proposal')
      else params[:ipable_type] ==  'Organisation'
        @bips = Package::Bip.where(:ipable_type == 'Organisation')
      end
  </code></pre>
  
  <p>But, when I save all of this and try it, I get the wrong results.</p>
  
  <p>At the moment, there are 4 instances of Package::Bip in the db. </p>
  
  <pre><code>Package::Bip.pluck(:ipable_type)
     (0.8ms)  SELECT "package_bips"."ipable_type" FROM "package_bips"
   =&gt; ["Proposal", "Proposal", "Proposal", "Organisation"] 
  </code></pre>
  
  <p>3 belong to a proposal and 1 belongs to an organisation.</p>
  
  <p>The 3 that belong to proposals each belong to a different proposal.</p>
  
  <pre><code>Package::Bip.pluck(:ipable_id)
     (0.8ms)  SELECT "package_bips"."ipable_id" FROM "package_bips"
   =&gt; [15, 13, 16, 1] 
  </code></pre>
  
  <p>My objective is that a proposal show view or an organisation show view should only show the Bips that belong to that specific proposal.</p>
  
  <p>However, when I render my proposal show view, which has:</p>
  
  <pre><code>&lt;%= link_to proposal_package_bips_path(@proposal) do %&gt; 
  </code></pre>
  
  <p>In turn, my views/package/bips/index.html.erb has:</p>
  
  <pre><code>&lt;% @bips.each do |ip| %&gt;
     &lt;%= ip.title.titleize %&gt;
        &lt;%#= link_to 'More details', package_bip_path(ip) %&gt; 
  </code></pre>
  
  <p>I expect this view to render a list containing 1 package_bip instance. Instead I get all 4 instances listed (2 of the proposal.bips belong to a different proposal and one of the bips belongs to an Organisation). None of those should be rendered in the index.</p>
  
  <p>Further, I can't add a link in my bips/index.html.erb to the bips/show.html.erb. This is because that link looks like:</p>
  
  <pre><code>&lt;%= link_to 'More details', package_bip_path(ip) %&gt; &lt;
  </code></pre>
  
  <p>When I try to render the index with that link in it, I get an error that says:</p>
  
  <pre><code>undefined method `package_bip_path' for #&lt;#&lt;Class:0x007fbce68389c0&gt;:0x007fbcfdc31c18&gt;
  </code></pre>
  
  <p>I think maybe the link needs to include either proposal or organisation.</p>
  
  <p>My routes are nested:</p>
  
  <pre><code>resources :proposals do 
      namespace :package do
        resources :bips 
      end
  
  resources :organisations do 
    namespace :package do
      resources :bips 
    end
  </code></pre>
  
  <p>From the console, I can search with the filters I want to apply. </p>
  
  <pre><code>p = Proposal.last
    Proposal Load (4.8ms)  SELECT  "proposals".* FROM "proposals" ORDER BY "proposals"."id" DESC LIMIT $1  [["LIMIT", 1]]
   =&gt; #&lt;Proposal id: 16, user_id: 4, title: "test tenor", description: "test tenor",  created_at: "2016-11-08 21:58:38", updated_at: "2016-11-08 21:58:38"&gt; 
  2.3.1p112 :199 &gt; p.bips
    Package::Bip Load (0.3ms)  SELECT "package_bips".* FROM "package_bips" WHERE "package_bips"."ipable_id" = $1 AND "package_bips"."ipable_type" = $2  [["ipable_id", 16], ["ipable_type", "Proposal"]]
   =&gt; #&lt;ActiveRecord::Associations::CollectionProxy [#&lt;Package::Bip id: 19, identifier: "test tenor", description: nil, conditions: "test tenor", ipable_id: 16, ipable_type: "Proposal", created_at: "2016-11-08 21:58:38", updated_at: "2016-11-08 21:58:38", title: "test tenor", status: nil, classification: "Copyright"&gt;]&gt; 
  2.3.1p112 :200 &gt; p.bips.count
     (3.5ms)  SELECT COUNT(*) FROM "package_bips" WHERE "package_bips"."ipable_id" = $1 AND "package_bips"."ipable_type" = $2  [["ipable_id", 16], ["ipable_type", "Proposal"]]
   =&gt; 1 
  </code></pre>
  
  <p>But this doesn't carry over to the code in any of my attempts.</p>
  
  <p>Can anyone refer me to resources that can help me figure out how to setup my polymorphic views so that they work to filter correctly and so that I can use the typical index links (e.g., to show/edit) so that they can be recognised as belonging to one or the other of Proposal/Organisation?</p>
  
  <p><strong>UPDATE</strong></p>
  
  <p>I've now found <a href="http://thelazylog.com/polymorphic-routes-in-rails/" rel="nofollow noreferrer">this</a> post.</p>
  
  <p>I tried adopting the process it suggests by:</p>
  
  <ol>
  <li><p>Changing create action in proposals controller to:</p>
  
  <p>def create
          if params[:organisation_id]
            parent = Organisation.find(params[:organisation_id])
          elsif params[:proposal_id]
            parent = Proposal.find(params[:proposal_id])
          end</p>
  
  <pre><code>bip = Package::Bip.new
  Package::Bip.ipable = parent
  # @bip = Package::Bip.new(bip_params)
  # authorize @bip
  
  respond_to do |format|
    if @bip.save
      format.html { redirect_to @bip }
      format.json { render :show, status: :created, location: @bip }
    else
      format.html { render :new }
      format.json { render json: @bip.errors, status: :unprocessable_entity }
    end
  end
  </code></pre>
  
  <p>end</p></li>
  <li><p>Changing the proposal view to:</p>
  
  </li>
  </ol>
  
  <p>When I try this, I get no errors, but all of the Package::Bips are displayed in a proposal show view.</p>
  
  <p>This is despite there being Package::Bips which have an organisation id.</p>
  
  <pre><code>Package::Bip.all.pluck(:ipable_type)
     (0.9ms)  SELECT "package_bips"."ipable_type" FROM "package_bips"
   =&gt; ["Proposal", "Proposal", "Proposal", "Organisation", "Proposal"] 
  </code></pre>
  
  <p>When I restart the server and try again, I get an error message that says:</p>
  
  <pre><code>undefined method `empty?' for #&lt;Class:0x007ff20920e218&gt;
  </code></pre>
  
  <p>The error message points to my new line:</p>
  
  <pre><code>&lt;%= polymorphic_path(@proposal, Package::Bip) %&gt;
  </code></pre>
  
  <p>The log shows:</p>
  
  <pre><code>Started POST "/__better_errors/3f34303f5f5c670f/variables" for ::1 at 2016-11-13 10:58:13 +1100
    Package::Bip Load (0.4ms)  SELECT "package_bips".* FROM "package_bips" WHERE "package_bips"."ipable_id" = $1 AND "package_bips"."ipable_type" = $2  [["ipable_id", 15], ["ipable_type", "Proposal"]]
  </code></pre>
  
  <p>This <a href="https://stackoverflow.com/questions/20624266/rails-polymorphic-link-for-nested-index-action">post</a> shows a similar problem, which is solved by adding '[]' to the path.</p>
  
  <p>When I then try:</p>
  
  <pre><code>&lt;%= link_to polymorphic_path([@proposal, Package::Bip]) do  %&gt;
  </code></pre>
  
  <p>I still get a list of all of the bips (even those which belong to an organisation or a proposal with a different id).</p>
  
  <p>What I can see from the log though might be a clue (if it is  - its going over my head). </p>
  
  <pre><code>Started GET "/proposals/15/package/bips" for ::1 at 2016-11-13 11:24:32 +1100
  Processing by Package::BipsController#index as HTML
    Parameters: {"proposal_id"=&gt;"15"}
    User Load (1.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 4], ["LIMIT", 1]]
    Rendering package/bips/index.html.erb within layouts/application
    Package::Bip Load (0.6ms)  SELECT "package_bips".* FROM "package_bips"
    Rendered package/bips/index.html.erb within layouts/application (5.4ms)
  </code></pre>
  
  <p>the log doesnt seem to show any indication that it is applying proposal or proposal id filters to the package_bips.</p>
  
  <p>This doesnt make any sense to me, because my routes are only available with a prefix of either organisation or proposal:</p>
  
  <pre><code>rake routes | grep package_bip
              organisation_package_bips GET      /organisations/:organisation_id/package/bips(.:format)                  package/bips#index
           new_organisation_package_bip GET      /organisations/:organisation_id/package/bips/new(.:format)              package/bips#new
          edit_organisation_package_bip GET      /organisations/:organisation_id/package/bips/:id/edit(.:format)         package/bips#edit
               organisation_package_bip GET      /organisations/:organisation_id/package/bips/:id(.:format)              package/bips#show
                  proposal_package_bips GET      /proposals/:proposal_id/package/bips(.:format)                          package/bips#index
               new_proposal_package_bip GET      /proposals/:proposal_id/package/bips/new(.:format)                      package/bips#new
              edit_proposal_package_bip GET      /proposals/:proposal_id/package/bips/:id/edit(.:format)                 package/bips#edit
                   proposal_package_bip GET      /proposals/:proposal_id/package/bips/:id(.:format)                      package/bips#show
  </code></pre>
  
  <p>Further still, when I try to use the show path in the last linked post, in my views/package/bips/index.html.erb as:</p>
  
  <pre><code> &lt;% @bips.each do |ip| %&gt;
      &lt;%= link_to polymorphic_path([@ipable, ip]) %&gt;
  </code></pre>
  
  <p>I then get an error which says:</p>
  
  <pre><code>undefined method `package_bip_path' for #&lt;#&lt;Class:0x007f9e8ac29248&gt;:0x007f9e939c9508&gt;
  </code></pre>
  
  <p><strong>TARYN'S SUGGESTIONS FOR SEARCHING FOR PROBLEMS</strong></p>
  
  <p>Background. In my proposal controller, my proposals are defined as:</p>
  
  <pre><code>def set_proposal
     @proposal = Proposal.find(params[:id])
  end
  </code></pre>
  
  <p>In the console, I try:</p>
  
  <pre><code>params = {:proposal_id =&gt; 15}
   =&gt; {:proposal_id=&gt;15} 
  
  
  2.3.1p112 :031 &gt; @proposal = Proposal.find(params[:proposal_id])
    Proposal Load (0.7ms)  SELECT  "proposals".* FROM "proposals" WHERE "proposals"."id" = $1 LIMIT $2  [["id", 15], ["LIMIT", 1]]
   =&gt; #&lt;Proposal id: 15, user_id: 4, title: "testing filter", description: "testing filter", byline: "testing filter", nda_required: true, created_at: "2016-11-08 00:59:09", updated_at: "2016-11-08 00:59:09"&gt; 
  
  2.3.1p112 :033 &gt; @proposal.bips
    Package::Bip Load (0.7ms)  SELECT "package_bips".* FROM "package_bips" WHERE "package_bips"."ipable_id" = $1 AND "package_bips"."ipable_type" = $2  [["ipable_id", 15], ["ipable_type", "Proposal"]]
   =&gt; #&lt;ActiveRecord::Associations::CollectionProxy [#&lt;Package::Bip id: 17, identifier: "testing filter", description: nil, conditions: "testing filter", ipable_id: 15, ipable_type: "Proposal", created_at: "2016-11-08 00:59:09", updated_at: "2016-11-08 00:59:09", title: "testing filter", status: nil, classification: "Patent"&gt;, #&lt;Package::Bip id: 21, identifier: "dd", description: nil, conditions: "dd", ipable_id: 15, ipable_type: "Proposal", created_at: "2016-11-10 22:47:54", updated_at: "2016-11-10 22:47:54", title: "ldsjflkjklsdjfl", status: nil, classification: "Design"&gt;]&gt; 
  2.3.1p112 :034 &gt; @proposal.bips.count
     (6.3ms)  SELECT COUNT(*) FROM "package_bips" WHERE "package_bips"."ipable_id" = $1 AND "package_bips"."ipable_type" = $2  [["ipable_id", 15], ["ipable_type", "Proposal"]]
   =&gt; 2 
  </code></pre>
  
  <p>This gives the correct result.</p>
  
  <p>In the proposal controller, show action, I have:</p>
  
  <pre><code>def show
      @images = @proposal.images
      byebug
      puts 'testing proposal controller'
      @bips = @proposal.bips#.where(ipable_type: 'Proposal')
    end
  </code></pre>
  
  <p>When I try this, I can explore the proposal params:</p>
  
  <pre><code>params
  &lt;ActionController::Parameters {"controller"=&gt;"proposals", "action"=&gt;"show", "id"=&gt;"15"} permitted: false&gt;
  (byebug) proposal_params
  *** ActionController::ParameterMissing Exception: param is missing or the value is empty: proposal
  
  nil
  </code></pre>
  
  <p>Others who have this problem attribute it to the 'require' statement in their strong params method.</p>
  
  <p>My proposal_params is defined as:</p>
  
  <pre><code>def proposal_params
        params.require(:proposal).permit(:title, :description, :byline, :nda_required, :randd_maturities_list,
          #Package
          bips_attributes:            [:id, :status, :classification, :identifier, :conditions, :title, :_destroy,
            tenor_attributes:           [:id, :express_interest, :commencement, :expiry, :enduring, :repeat, :frequency, :_destroy]
  
          ],
  
  
         )
      end
  </code></pre>
  
  <p>I think its correct.</p>
  
  <p>These messages are odd though, because I can also go through each whitelisted item in the bye bug statement and get the right response. For example:</p>
  
  <pre><code> @proposal.id
  15
  </code></pre>
  
  <p>When I try exploring with bye bug in the Package::bips controller, index action, I can see:</p>
  
  <pre><code>params.inspect
  "&lt;ActionController::Parameters {\"controller\"=&gt;\"package/bips\", \"action\"=&gt;\"index\", \"proposal_id\"=&gt;\"15\"} permitted: false&gt;"
  </code></pre>
  
  <p>The permitted: false attribute appears to be a problem all over my code.</p>
  
  <p>That's my next line of enquiry.</p>