How can I pass more than 2 arguments to partial? - ruby-on-rails

I want to pass 2 arguments such as topic and icon_photo.
How can I do that?
undefined method `icon_photo?'
I got this error with the code below.
view
<div class="Topic">
<% #community.topics.each do |topic| %>
<%= render 'topics/topic', :topic => topic, :icon_photo => topic.user.profile.avatar %>
<% end %>
</div>

You can pass a locals hash:
<div class="Topic">
<% #community.topics.each do |topic| %>
<%= render 'topics/topic', locals: {topic: topic, icon_photo: topic.user.profile.avatar, etc: 'blabla' } %>
<% end %>
</div>
See some documentation here:
http://www.tutorialspoint.com/ruby-on-rails/rails-render.htm
A little improvement can be mabe, you can render your collection like this:
<div class="Topic">
<%= render partial: 'topics/topic', collection: #community.topics %>
</div>
# in your partial topics/_topic.html.erb:
<% icon_photo = topic.user.profile.avatar %>

Related

How to call a form from an element

I have Post with nested elements who also have different nested form (text for this example) according to a :cat variable.
To create the texts I'm using a post method create_element with a variable (cat = 1). And I would like to call an AJAX method to render the new text created into my post form.
My problem: I don't know how to call the text nested_form created directly into my AJAX method.
My code :
Post form (posts/new):
<%= simple_form_for #post do |f| %>
<div class="elements">
<%= f.fields_for :elements do |element| %>
<%= render 'posts/element_field', f: element %>
<% end %>
</div>
<div class="btn_add_element_area">
<a href="/posts/<%=#post.id%>/create_element?cat=1" data-method="patch" data-remote="true">
<i class="fa fa-font"></i>
</a>
</div>
<%= f.submit "Publish", class: "btn" %>
<% end %>
Post form (posts/_element_field):
<div class="element_form" id="element_form<%= f.object.id %>">
<div class="undisplay">
<%= f.number_field :cat %>
</div>
<%- if f.object.cat == 1 %>
<%= f.fields_for :post_texts do |text| %>
<%= render 'posts/elements/text_field', f: text %>
<% end %>
<% end %>
</div>
Post form (posts/_text_field):
<%= f.text_area :content %>
Post controller (create_element) :
def create_element
if params[:cat] == "1"
#element = Element.create(post: #post, cat: 1)
Text.create(element: #element)
end
respond_to do |format|
format.js {render 'elements/create'}
end
end
And the AJAX method (elements/create) :
$('.elements').append("<%= j render partial: 'posts/element_field', locals: {f: #element} %>");
Error = undefined method `object'
The problem is that in the AJAX file I call the #element created for my f variable instead of calling the form of this #element.
I also tried something like that for the AJAX method, but still not working :
<% form_for(#element) do |elm| %>
$('.elements').append("<%= j render partial: 'posts/element_field', locals: {f: elm} %>");
<% end %>
Error = undefined method `element_path'
Or
<%= simple_form_for(#post) do |p| %>
<%= p.fields_for :elements, #element do |elm| %>
$('.elements').append("<%= j render partial: 'posts/element_field', locals: {f: elm} %>");
<% end %>
<% end %>
No error but nothing happen
If you have any ideas to solve that, I would really appreciate !
PS: And ideas to improve the question title are welcome !!

Reusing a partial in the same page

I have a controller with 3 objects and i want to call the same partial three time with each object
class HomeController < ApplicationController
def index
#evaluations_teams = Evaluation.eager_load(:user).where(users: {status: true}).where(team_id: current_user.student_details.last.team_id).all.order(created_at: :desc).limit 5
#evaluations_stage = Evaluation.eager_load(:user).where(users: {status: true}).where(stage_id: current_user.student_details.last.stage_id).all.order(created_at: :desc).limit 5
#evaluations_schools = Evaluation.eager_load(:user).where(users: {status: true}).where(school_id: current_user.student_details.last.school_id).all.order(created_at: :desc).limit 5
end
end
INDEX.HTML.ERB
<%= render 'home/partials/loop_areas', locals: {evaluations:#evaluations_teams} %>
<%= render 'home/partials/loop_areas', locals: {evaluations:#evaluations_stage} %>
<%= render 'home/partials/loop_areas', locals: {evaluations:#evaluations_schools} %>
Partial: home/partials/_loop_areas.html.erb
<% #evaluations.each do |evaluation| %>
<div class="div-card-infosaluno">
<div class="card-aluno"><%= evaluation.user.full_name %></div>
<div class="card-serie"><%= "#{evaluation.stage.name} · #{evaluation.school.name}" %></div>
</div>
<% end %>
This returns:
undefined method `each' for nil:NilClass
on <% #evaluations.each do |evaluation| %>
How can i do this?
You're trying to access an instance variable #evaluations in your partial but it is not defined in the controller action.
You've to instead loop through the local variable evaluations.
<%# home/partials/_loop_areas.html.erb %>
<% evaluations.each do |evaluation| %>
...
<% end %>
And your view should be
<%= render 'home/partials/loop_areas', evaluations: #evaluations_teams %>
<%= render 'home/partials/loop_areas', evaluations: #evaluations_stage %>
<%= render 'home/partials/loop_areas', evaluations: #evaluations_schools %>
You can also pass a hash to the render method but I feel it is more verbose.
<%= render partial: 'home/partials/loop_areas', locals: { evaluations: #evaluations_schools } %>
Please try the below code in Partial: home/partials/_loop_areas.html.erb
It should work as you are expecting.
<% evaluations = local_assigns[:evaluations] %>
<% evaluations.each do |evaluation| %>
<div class="div-card-infosaluno">
<div class="card-aluno"><%= evaluation.user.full_name %></div>
<div class="card-serie"><%= "#{evaluation.stage.name} · #{evaluation.school.name}" %></div>
</div>
<% end %>
Thanks.

Trying to make my partial work

I need to iterate through two sets of values on the same web page so I wrote a partial to eliminate duplicate code. The two variables that I am trying to iterate through are #bookmarks and #liked_bookmarks.
The partial is rendered properly if I use either #bookmarks or #liked_bookmarks in the partial it's self but then the only one of the value sets are displayed. in the code below I tried using #resource as a stand in that will have #bookmarks and #liked_bookmarks passed into it.
this is the partial that is located in app/views/bookmarks/_bookmarksandlikes.html.erb
<div>
<% #resource.each do |x| %>
<%= x.url%>
<% end %>
<div>
and this is the code for the page that I am calling the above partial on located in app/views/users/show.html.erb
<h1>My Blocmarks</h1>
<p>Find me in app/views/users/show.html.erb</p>
<div>
<h1>Blockmarks I have created </h1>
<div class =row>
<%= render partial: 'bookmarks/bookmarksandlikes', locals: { topic: #bookmarks} %>
</div>
</div>
<div>
<h1>Blockmarks I have liked
<%= render partial: 'bookmarks/bookmarksandlikes', locals: { topic: #liked_bookmarks} %>
</h1>
</div>
You're close. Instead of #resource just use topic, which you are passing in as a local.
<div>
<% topic.each do |x| %>
<%= x.url%>
<% end %>
<div>
Since you are not passing #resource into partial and passing only topic variable you need to do it
<div>
<% topic.each do |x| %>
<%= x.url%>
<% end %>
<div>
Instead of:
<div>
<% #resource.each do |x| %>
<%= x.url%>
<% end %>
<div>
Do it:
<div>
<% topic.each do |x| %>
<%= x.url%>
<% end %>
<div>
Because you pass the object on locals: { topic: #liked_bookmarks} you should use topic instead of using any instance that is not initialize.

Combine 2 models into one array, paginate, and force 1 partial

I want to combine data from two different models, combine it into one array and use the will_paginate gem to paginate the results in my view on that collection. I'm already using require 'will_paginate/array' to allow for a normal, non-ActiveRecord array and its all working properly.
My problem is that its using two different partials to render the entries based on which model the data originated from. How do I force it render one specific partial?
controller
def sample_action
page = params[:page] || 1
#collection = []
#car.messages.select {|msg| #collection << msg}
Alerts.where(car_id: #car.id).select {|alerts| #collection << alerts}
#collection = #collection.sort{|a,b| b[:created_at] <=> a[:created_at]}
#collection = #collection.paginate(:page => page, :per_page => 30)
respond_to do |format|
format.html { render :sample_action }
end
end
view
<% if #collection.count > 0 %>
<div class="row">
<div class="col-xs-12">
<div id="car-alerts" class="car-alerts-all">
<%= render #collection -%>
</div>
</div>
</div>
<%= will_paginate #collection -%>
<% else %>
<p class="no-alerts-message">Your car is healthy</p>
<% end %>
car partial
Car - <%= collection.id %>
<br>
alert partial
Alert - <%= collection.id %>
<br>
I would use the fact that you basically just want to output the model name and do this:
<% if #collection.count > 0 %>
<div class="row">
<div class="col-xs-12">
<div id="car-alerts" class="car-alerts-all">
<%- #collection.each do |obj| -%>
<%= obj.class.to_s -%> - <%= obj.id %>
</div>
</div>
</div>
<%= will_paginate #collection -%>
<% else %>
<p class="no-alerts-message">Your car is healthy</p>
<% end %>
but it would break easily if you wanted to add labels different to class names.
You need to iterate over each item in the collection and have a conditional based on the model type, so for example:
<div id="car-alerts" class="car-alerts-all">
<% #collection.each do |car_or_alert| %>
<%=
if car_or_alert.is_a?(Alert)
render :alert #you need to add locals here as well, but it unclear what locals you are using
else
render :car #see above
end %>
<% end %>
</div>
Turns out it was as simple as setting the partial from render
<% if #collection.count > 0 %>
<div class="row">
<div class="col-xs-12">
<div id="car-alerts" class="car-alerts-all">
<%= render collection: #collection, partial: 'car/partial_name' -%>
</div>
</div>
</div>
<%= will_paginate #collection -%>
<% else %>
<p class="no-alerts-message">Your car is healthy</p>
<% end %>
This being the key change -
<%= render collection: #collection, partial: 'car/partial_name' -%>

Passing multiple variables to partial

I get error in partial line #1: undefined local variable or method 'level'
Code in my view:
<div id="comments">
<% level = 0%>
<% #comments.each do |comment| %>
<%=render partial: 'comments/single_comment', locals: {level: level, comment: comment} %>
<% end %>
<% if 0 < level %>
<% (level).times do %>
</div>
<% end %>
<% end %>
</div>
</div>
And partial first lines:
<% if comment.level < level %>
<% (level - comment.level).times do %>
</div>
<% end %>
<% end %>
Any idea what's wrong here?
Looks like this code should be work(it's no so good, but it should be work)
I think problem that you use your partial (comments/single_comment) elsewhere in some part of code what we didn't see without 'level local' :)
seems like the code is right .. try to check if you have any partial view that use single_comment filename ... and also you can use collection instead doing a loop
<%= render partial: 'comments/single_comment', collections: #comments, locals: { level: level } %>
You are passing arguments to the partial in a wrong way. update it to following.
<%=render partial: 'comments/single_comment', locals: => {:level => level, :comment => comment} %>
now you can access your objects in partials as follows
<% if locals[:level] < level %>
<% (level - locals[:level]).times do %>
</div>
<% end %>
<% end %>

Resources