简体   繁体   中英

Passing variables to rails partials

I have a table that is used to show the number of clients associated with certain team members. The code for each of the tables is basically the same so I thought I would dry it with some partials with local variables passed to it.

Here is the original code.

<thead>
    <tr>
      <th>Name </th>
      <th>Clients </th>
    </tr>
  </thead>
  <tbody>
    <% @strategists.each do |strategist| %>
      <tr>
        <td><%=link_to strategist.name, strategist %> </td>
        <td><%=strategist.clients.count%> </td>
        <td> <%= link_to 'Edit', edit_strategist_path(strategist) %> | <%= link_to 'Destroy', strategist, method: :delete, data: { confirm: 'Are you sure?' } %>

      </td>
    <% end %> 
  </tbody>

So I have tried to replace with with a more generic form that I can pass variables to.

<table class="table table-striped">
  <thead>
    <tr>
      <th>Name </th>
      <th>Clients </th>
    </tr>
  </thead>
  <tbody>
    <% team_member_global.each do |team_member| %>
      <tr>
        <td><%=link_to team_member.name, team_member %> </td>
        <td><%=team_member.clients.count%> </td>
        <td> <%= link_to 'Edit', edit_team_member_path(team_member) %> | <%= link_to 'Destroy', team_member, method: :delete, data: { confirm: 'Are you sure?' } %>

      </td>
    <% end %> 
  </tbody>
</table>

Here is the code rendering the partial.

<%= render partial: "shared/team_member_index", locals: {
  team_member_global: @strategist,
  new_team_member: "New Strategist",
  new_team_member_path: new_strategist_path,
  edit_team_member_path: edit_strategist_path
  }%>

This leads me to a nil class error for <% team_member_global.each do |team_member| %>.

It also leads to an error with the edit_strategist_path wanting an [:id], but if I pass it as a string it can't find the route.

What is the correct way to pass these variables in?

Update

Following the advice outlined below as well as following up a few leads this is the outcome.

This is the shared partial for the index page of each team member. I used @anthony-e's advice of using collections to output my table.

<h1 class="page-header"> <%=team_member_capitalised%> </h1>
<div class="table-responsive">
<table class="table table-striped">
  <thead>
    <tr>
      <th>Name </th>
      <th>Clients </th>
    </tr>
  </thead>
  <tbody>
    <%= render partial: "shared/team_member_table", collection: team_member_global, as: :team_member, locals: {team_members: team_member_global} %>
  </tbody>
</table>        
</div>
<%= paginate team_member_global, :window => 2 %>   
<div id="link_button">
<%= link_to new_team_member, new_team_member_path, class: "btn btn-default", role: "button"  %>
</div>

This is the table partial. Thanks to @margo I ended up down the path of looking at method sends which lead me to discover polymorphic paths, which solved the main problem of having to pass through the edit_team_member_path. Instead of passing it through I can construct it dynamically.

<tr>
  <td><%=link_to team_member.name, team_member %> </td>
  <td><%=team_member.clients.count%> </td>
  <td> <%= link_to 'Edit', edit_polymorphic_path(team_member) %> | <%= link_to 'Destroy', team_member, method: :delete, data: { confirm: 'Are you sure?' } %>
</tr>

This is where I call the partial on my index page for each team member (obviously changing the variables where needed). @dharam pointed out that I was using @strategist instead of @strategists, which allowed properly render my collection, and highlighted my key problem.

<%= render partial: "shared/team_member_index", locals: {
    team_member: @strategist,
  team_member_capitalised: "Strategist",
  team_members_path: strategists_path,
  team_member_global: @strategists,
  new_team_member: "New Strategist",
  new_team_member_path: new_strategist_path,
  }%>

Code working perfectly now, so thanks for everyone's help!

I think you need to assign @strategists to team_member_global , not @ strategist .

Also edit_strategist_path expects the strategist is passed to it so that it can deduce the id from it, which is required to generate the path. It is a method, so if you pass it as a string, it won't generate the path.

Your question is not clear where the partial fits in, where you are using variables and strings. You may need to construct your paths from the class name you are passing in using one of rails' helpers and using send.

<% @strategists.each do |strategist| %>
  <%= render partial: "shared/team_member_index", locals: {
    team_member_global: strategist, 
    new_team_member: "New Strategist",
    new_team_member_path: new_strategist_path,
    edit_team_member_path: edit_strategist_path
  }%>

If the method is asking for an id, give it strategist.id.

There's a lot you can do to simplify your code. First, you don't need to pass any of those variables because they're shared within all your views for that request.

Also, since you're rendering a collection you can use replace your loop with the following:

= render partial: "shared/team_member_index", collection: @strategists, as: :strategist

Now, a variable named strategist will be passed to the partial for each element in your @strategists like so:

# Within _team_member_index partial:
<td><%=link_to strategist.name, strategist %> </td>
<td><%=strategist.clients.count%> </td>
<td> <%= link_to 'Edit', edit_strategist_path(strategist) %> | <%= link_to 'Destroy', strategist, method: :delete, data: { confirm: 'Are you sure?' } %>

This will be much cleaner and all without having to pass a single variable.

Finally, for consistency I'd recommend renaming your partial to _strategist, or whatever the name of the record that the partial represents.

Collection can be a bit confusing at first, but are super powerful and can really help keep views clean and simple.

Some more good info here: https://robots.thoughtbot.com/rendering-collections-in-rails http://guides.rubyonrails.org/layouts_and_rendering.html

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM