Trying to make my partial work - ruby-on-rails

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.

Related

Using Loop Variable to Set the id Attribute

I have the following code:
<% #electives.each do |elective| %>
<div>
</div>
<% end %>
I would like to set the id of the div to elective.name, but I don't know how to do it, or whether this works:
<% #electives.each do |elective| %>
<div id="elective.name">
</div>
<% end %>
Is it possible to do this in Rails?
Thanks.
You can use <%= ruby variable %> block within erb file to add ruby values within your pages
<div id="<%= elective.name %>">
As an alternative solution, you can use the rails tag helper
<% #electives.each do |elective| %>
<%= tag.div id: elective.name do %>
...
<% end %>
<% end %>

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 %>

How can I pass more than 2 arguments to partial?

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 %>

Passing markup into a Rails Partial

Is there any way of doing something equivilant to this:
<%= render partial: 'shared/outer' do %>
<%= render partial: 'shared/inner' %>
<% end %>
Resulting in
<div class="outer">
<div class="inner">
</div>
</div>
Obviously there would need to be a way of marking up 'shared/outer.html.erb' to indicate where the passed in partial should be rendered:
<div class="outer">
<% render Here %>
</div>
In my specific case I have a generic page header, consisting of a header and subheader, that is shared across all pages, but would like the option of passing in page-specific markup to that header to be rendered below the title and subtitle.
I'd use content_for :
<% content_for :subheader do %>
<%= render partial: 'shared/inner' do %>
<% end %>
<%= render partial: 'shared/outer' %>
Then in shared/outer :
<div class="outer">
<%= yield(:subheader) %>
</div>
You can put whatever you'd like in the content_for block and use it as many times as you'd like, just change the key name (here subheader)

Resources