Ruby on Rails passing parameters to partials - ruby-on-rails

This is my .erb file;
<% if #comment.reviewer_notes && current_user.type == "User::Reviewer"%>
<% #comment.reviewer_notes.each do |reviewer_note| %>
<?= reviewer_note.rating %> <-- this "works" ie prints out rating on screen
<%= render 'partials/comments/form' %>
this is my .erb partial;
<div class="admin-rating stars clear">
<%= reviewer_note.rating %> <-- this does not work.
</div>
The error I get is;
undefined method `reviewer_rating' for #TipComment:0x007f8b38e29328>
How do I pass in reviewer_note.rating?

<%= render partial: 'reviewer_note_rating', locals: {reviewer_note: reviewer_note} %>

You should pass it as a variable to Partial.
<%= render 'partials/comments/form', note_rating: reviewer_note.rating %>

Related

Rendering a partial inside a loop

I'm trying to render the following partial:
<% #accepted.each do |question| %>
<div class="questions-container__content">
<div class="questions-container__accepted-content">
...
</div>
<%= render 'question_buttons', collection: #accepted %>
</div>
<% end %>
with _question_buttons.html.erb:
<div class="links-container__button-group" id="link-buttons">
<%= link_to "View submission", coin_question_path(question.coin, question.id), class: "primary-small","data-turbolinks"=>"false" %>
<%= link_to "Edit", edit_coin_question_path(question.coin, question.id), class: "primary-small","data-turbolinks"=>"false" %>
<% if !question.accepted? %>
<%= link_to "Activate" , activate_coin_question_path(question.coin, question.id), class: "primary-small","data-turbolinks"=>"false" %>
<% else %>
<%= link_to "Deactivate" , deactivate_coin_question_path(question.coin, question.id), class: "primary-small","data-turbolinks"=>"false" %>
<% end %>
<% if current_user.admin? %>
<%= link_to (question.rejected ? "Restore" : "Reject"), reject_coin_question_path(question.coin, question.id), class: "primary-small","data-turbolinks"=>"false" %>
<% end %>
</div>
I get the following error:
undefined local variable or method `question' for #<#<Class:0x00007fece6998d08>:0x00007fed02072bb8>
What am I doing wrong here?
I believe the issue is that you need to pass the question variable from each loop in the parent view through to the partial using locals which allows the partial to access it.
<%= render 'question_buttons', locals: { question: question } %>
First:
When rendering a collection, each item of the collection is passed to the partial as a local variable with the same name as partial itself. It means that for this call:
<%= render 'question_buttons', collection: #accepted %>
the partial question_buttons will be called for each item of #accepted array; that item will be available inside partial as question_buttons.
If you want to use another name for the item, for example question, you need to call it as:
<%= render 'question_buttons', collection: #accepted, as: :question %>
Another option -- just rename the partial to question:
<%= render 'question', collection: #accepted %>
Second:
In your code snippet rendering collection is called on each iteration of the loop over #accepted elements. If #accepted has 8 elements, for example, the partial will be rendered 8 times for each of these elements, ie 8 * 8 = 64 times in total. I suspect that it's not what you want to achieve. Your code looks like question_buttons partial needs to be rendered for each element of #accepted only once. In this case using collection param has no sense here. Just pass a local variable question into the partial:
<%= render 'question_buttons', question: question %>

How to create a HTML template in Rails?

I have a long code. For example:
<% Post.limit(10).offset(10).order(id: :desc).each do |post| %>
######## FROM HERE ###########
<% unless post.image.blank? %>
<% img = post.image.split(' ') %>
<% if post.post_type == 1 %>
<div class="post_type1">
<h1>
<a href="post/<%= post.slug %>">
<%= post.title %>
</a>
</h1>
</div>
<% end %>
<% end %>
####### TO HERE #########
<% end %>
So, I want to make this part(FROM HERE <-> TO HERE part) like a template. So I wrote first line, later render or something else, I do not know and the last line for displaying all the page. Can you help me with it?
Just put it in a file (lets call it _post.html.erb) and include it like:
<% Post.limit(10).offset(10).order(id: :desc).each do |post| %>
<%= render partial: 'post', locals: { post: post } %>
<% end %>
Note the use of locals: { post: post } that passes the variable post in your loop to your partial. Another thing to note is that your file name starts with an underscore (_) which is left out when you render the partial.
Read more about partials in Rails guide.

How to pass variables to partials?

I have a common problem that normally I would solve with locals, but this time wont work.
I have the following block:
<% #user.followers.each do |follower| %>
<%= render "follower_card" %>
<% end %>
And the following partial:
<div class="row follower-card">
<%= image_tag follower.avatar_url(:smallthumb), class: "col-4 inline avatar_medium circle" %>
<ul class="col-8 inline">
<li><%= follower.name %></li>
<li><%= follower.location %></li>
<li class="lightgray small inline"><span class="bold"><%= follower.photos.count %></span> Spots</li> -
<li class="lightgray small inline"><span class="bold"><%= follower.albums.count %></span> Spotbooks</li>
</ul>
</div>
I'm getting the following error:
undefined local variable or method `follower' for #<#<Class:0x007fe791a4c8d0>:0x007fe799b14b98>
This should work (specifying the follower variable):
<%= render "follower_card", follower: follower %>
Anyway, I recommend you to use collection rendering for performance reasons. Take a look here: http://guides.rubyonrails.org/layouts_and_rendering.html. Should be something like:
<%= render "follower_card", collection: #user.followers %>
Related question: Render partial :collection => #array specify variable name
Note
Old syntax to pass variables to partials is also valid (verbose, but less elegant IMHO):
<%= render partial: "follower_card", locals: { follower: follower } %>
This is because you are not passing the variable to the partial. The scope of the partial is limited to itself, and you are not making follower available inside. You will have to use:
<% #user.followers.each do |follower| %>
<%= render "follower_card", locals: {follower: follower} %>
<% end %>
Is the proper way.
<%= render "follower_card", follower: follower %>
or
<%= render partial: "follower_card", locals: {follower: follower} %>

check if Rails partial is empty

I have a main page that is responsible for HTML/CSS styling, but some of the contents come from partials. A partial receives some locals or params, i.e. current_user or person, and displays information if any.
Is there a way for me to check if a partial rendered anything? My end goal is something like this:
<% if my_partial can render something %>
<div class="css_for_something">
<%= render(partial: 'my_partial', locals: {...} ) %>
<% else %>
<div class="css_for_no_info">
<%= render something else %>
<% end %>
I do not want the partials to handle styling logic; they just need to display content if any. Conversely, the main page should not know anything about the logic in the partial(s), such as checking values or querying the database.
Thank you
Unfortunately, Chris Peter's solution did not work for me on rails 4.2.4, as render_to_string seems to not be available in views.
However, the following worked (rails 4.2.4):
<% partial_content = render partial: 'my_partial' %>
<% if partial_content.present? %>
<%= partial_content %>
<% else %>
<%# rendered if partial is empty %>
<% end %>
Be aware that the present? check really only checks if what was rendered is empty. If, something, e.g. a HTML comment, is returned, the check returns false.
Try storing the value generated by render_to_string in a variable:
<% partial_content = render_to_string(partial: 'my_partial', locals: {...} ).strip %>
Then you can see if it contains any content:
<% if partial_content.present? %>
<%= partial_content %>
<% else %>
<div class="css_for_no_info">
<%= render something else %>
</div>
<% end %>

Render to partial by Ajax in Rails App

I have almost done! but I have an issue, in my Controller file have this:
def show
#user = User.find(params[:id])
#posts = #user.posts.paginate(page: params[:page])
end
Then I have this piece of code in my file show.html.erb:
<div class="span8">
<%= render 'follow_form' if signed_in? %>
<% if #user.posts.any? %>
<h3>Microposts (<%= #user.posts.count %>)</h3>
<div id='posts'>
<div class='page'>
<ol class="microposts">
<%= render #posts %>
</ol>
</div>
</div>
<% end %>
</div>
At the bottom of this file, I have a Javascript code that I have taken from the tutorial: https://github.com/amatsuda/kaminari/wiki/How-To:-Create-Infinite-Scrolling-with-jQuery
In the same folder I have the file index.js.erb with:
$("#articles").append("<div class='page'><%= escape_javascript(render(#users)) %></div>");
$("#posts").append("<div class='page'><%= escape_javascript(render(#posts)) %></div>");
In a partial _posts.html.erb have this:
<div class='article'>
<%= image_tag(user.picture_url, :width => 50) %>
<%= link_to user.name, user %>
<% if current_user.admin? && !current_user?(user) %>
| <%= link_to "delete", user, method: :delete,
data: { confirm: "You sure?" } %>
<% end %>
</div>
The first one already works in my file index.html.erb, the problem is with the second piece of code, when I try to render the partial at #post, It brings the follow log:
**
'nil' is not an ActiveModel-compatible object that returns a valid partial path.
Extracted source (around line #2):
1: $("#articles").append("<div class='page'><%= escape_javascript(render(#users)) %></div>");
2: $("#posts").append("<div class='page'><%= escape_javascript(render(#posts)) %></div>");
**
How can I render that partial?
Thanks a lot :D
I usually use the .js.erb template to render the partial into a var then set it on the page using JS. Be sure to escape_javascript the template content otherwise you will get JS errors.
<% template_html = render :partial => '_feed_item.html.erb' %>
<%="$('div#content').html('#{escape_javascript(template_html)}</div>');" %>
I think the above should work in erb. I use HAML so mine looks like:
-template_html = render :partial => 'partial_template'
!="$('div#content').html('#{escape_javascript(template_html)');"
Cheers.
Based on your In script I'm calling to /users?page=, and I was wondering that It may calls the line, you must make sure that your controller is populating the #posts variable if your view is using this. Can you show the controller method users?

Resources