Linking to associated models in INDEX view

2019-08-27 22:21发布

问题:

Just solved the problem of linking to associated models in my SHOW view here but the same answer doesn't work for my INDEX view.

What I'm trying to make work, and can't is the Manufacturer bit, which is a model that belongs_to Miniatures. The table comes out fine but I can't get the manufacturer to display and link properly. Sorry this wasn't clear.

My miniatures index.html.erb

<% provide(:title, 'All miniatures') %>
<h1>All miniatures</h1>

<%= will_paginate %>

<table border="0" cellpadding="10">
<th align="left">Name</th>
<th align="left">Material</th>
<th align="left">Manufacturer</th>
<th align="left">Scale</th>
<th align="left">Product Code</th>
<th align="left">Sculpted by</th>
<th align="left">Release date</th>
<% if current_user.try(:admin?) %><th align="left">Admin</th><% end %>
  <%= render @miniatures %>
</table>

<%= will_paginate %>

<h1> Import Miniatures</h1>

<%= form_tag import_miniatures_path, multipart: true do %>
  <%= file_field_tag :file %>
  <%= submit_tag "Import" %>
<% end %>

Which renders this partial to display the miniatures:

<tr>
  <td><%= link_to miniature.name, miniature %></td>  
  <td><%= miniature.material %></td>
  <td><%= link_to manufacturer.name, manufacturer_path(manufacturer)</td> 
  <td>scale</td> 
  <td><%= miniature.pcode %></td>
  <td>sculptor</td>
  <td><%= miniature.release_date %></td>
  <td><% if current_user.try(:admin?) %>
  <%= link_to "delete", miniature, method: :delete,
                                  data: { confirm: "You sure?" } %>
  <% end %></td></tr>

I can see that it can't work just the same as my view because there I had a named instance |manufacturer| that I don't have here. I guess then that I need to define it in the controller? Under Index?

Here is my (slightly cropped) MiniaturesController

class MiniaturesController < ApplicationController
       before_action :signed_in_user, only: [:new, :create, :edit, :update]
       before_action :admin_user,     only: :destroy

       def import
         Miniature.import(params[:file])
         redirect_to root_url, notice: "Miniatures imported."
       end

      def show
        @miniature = Miniature.find(params[:id])
      end

      def new
        @miniature = Miniature.new 
        @miniature.productions.build
        @miniature.sizes.build
        @miniature.sculptings.build
      end

      def create
        @miniature = Miniature.new(miniature_params)
        @production = @miniature.productions.build
        @size = @miniature.sizes.build
        @sculpting = @miniature.sculptings.build
        if @miniature.save
          redirect_to @miniature
        else
          render 'new'
        end
      end

      def edit
        @miniature = Miniature.find(params[:id])

      end

      def update
        @miniature = Miniature.find(params[:id])
         if @miniature.update_attributes(miniature_params)
          flash[:success] = "Miniature updated"
          redirect_to @miniature and return
        end
         end
       end
     end
          render 'edit'
      end

      def index
        @miniatures = Miniature.paginate(page: params[:page])
      end

      def destroy
        Miniature.find(params[:id]).destroy
        flash[:success] = "Miniature destroyed."
        redirect_to miniatures_url
      end

    private
        def miniature_params
          params.require(:miniature).permit(:name, :release_date, :material, :pcode, :notes, productions_attributes: [:id, :manufacturer_id, :miniature_id], sizes_attributes: [:id, :scale_id, :miniature_id], sculptings_attributes: [:id, :sculptor_id, :miniature_id])
        end

        def admin_user
          redirect_to(root_url) unless current_user.admin?
        end

        def signed_in_user
          unless signed_in?
            store_location
            redirect_to signin_url, notice: "Please sign in."
          end
      end
    end

回答1:

You shouldn't change your controller. The relationship between miniature and manufacturer should have been defined at the model level, e.g.:

class Miniature < ActiveRecord::Base
  belongs_to :manufacturer
end

class Manufacturer < ActiveRecord::Base
  has_many :miniatures
end

Your actual relation code may differ, but the above demonstrates the principles.

In your miniature partial (miniatures/_miniature.html.erb), a miniature's manufacturer is available as an attribute:

<td><%= link_to miniature.manufacturer.name, miniature.manufacturer %></td>

(NB: note you can include the object instance, and Rails' routing helpers will automatically convert it into the appropriate path, assuming you've specified resources :manufacturers in your routes.rb file).

I get the feeling you're struggling a bit with the way ActiveRecord associations work, and end up confusing yourself as a result.