Render a partial view in Rails is very straighforward. If you have a partial view file named _form.html.erb, in your view page, you could just do <%= render "form" %> . That's the most basic partial rendering. What about there are variables involved or the partial view needs to be refreshed triggered by an ajax call?

Let's look at a slightly more complicated case. First this is partial view mark up _restaurant_list.html.erb

<table>
<tr>
  <td onclick="changeVote('up', <%= mrs.id %>)"><img alt="upvote" src=<%=image_path("upvote.png")%>>
  </td>
  <td rowspan="3">
    <%= mrs.restaurant.name %>
  </td>
</tr>
<tr>
  <td><%= vote_count %></td>
</tr>
<tr>
  <td onclick="changeVote('down', <%= mrs.id %>)"><img alt="downvote" src=<%=image_path("downvote.png")%>>
  </td>
</tr>
</table>

There is a variable in the partial view, named <%=mrs%>. How is this variable passed in there? Here is show.html.erb page, where partial view's rendered.

<p>
  <strong>Title:</strong>
  <%= @meeting.title %>
</p>

<p>
  <strong>Description:</strong>
  <%= @meeting.description %>
</p>

<p>
  <strong>Date:</strong>
  <%= @meeting.date.in_time_zone %>
</p>

<div id="restaurant_table">
	<%= render partial: "restaurant_list", locals: {mrs: @meeting_mrs %>
</div>
		
<br>
<%= link_to 'Edit', edit_meeting_path(@meeting) %> |
<%= link_to 'Back', meetings_path %>
<%= render partial: "restaurant_list", locals: {mrs: @meeting_mrs} %> 

is how you pass the variable to the partial view.

Now let's say each time a user presses upvote/downvote image, it triggers an ajax call to update the votes in database. We will have an ajax call like this:

function changeVote(vote, mrs_id) {
  var id = '<%=@meeting_id%>';
  var url = "../meetings/" + id + "/" + "update_vote";
  $.ajax({
    url: url,
    type: "GET",
    data: {
      mrs_id: mrs_id, 
      vote: vote, 
      id: id
    },
    datatype: "json",
    success: function(data, textStatus, xhr){
      ...
    },
    error: function(request, status, error){
      console.log(error);
    },
  });
}

The goal is that when the call comes back, it refreshes the partial view. The method that ajax call invokes:

def update_vote
    mrs_id = params[:mrs_id]
    vote = params[:vote]
    id = params[:id]
    umv = Vote.new(:meeting_restaurant_selection_id=>mrs_id, :vote=>vote)
    umv.save
end

In order to make the partial view refresh correctly, the method need to render all the data back to the page. At the end of update_vote method, we need to specify:

mrs = Meeting.find(id).meeting_restaurant_selections 
render :partial=>"restaurant_list", :locals=>{:mrs=>meeting_mrs}

Also, inside the ajax call, when the call is successful, it should pass in the entire data:

success: function(data, textStatus, xhr){
      $("#restaurant_table").html(data)
    },

There, it completes the whole process.

In summary, there are three pieces to make it work right.

  • The html markup page where partial view is rendered passes varialbes via locals=>{variable name=>value}

  • The ajax call return has to put the data in html context using: (using jquery as an example)
    $(<id>).html(data)

  • ajax call method returns partial and do remember to pass in necessary params render :partial=>"restaurant_list", :locals=>{:mrs=>meeting_mrs}