Populating a bootstrap 3 dropdown - ruby-on-rails

I'm trying to populate this drop down with comments but only end up with the first comment instead of all of them.
<div class="dropdown">
<button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">Comments
<span class="caret"></span></button>
<% #comments.each do |z| %>
<% if z.post_id == post.id %>
<ul class="dropdown-menu">
<li><%= z.body %></li>
</ul>
</div>
<% end %>
controller:
class StaticPagesController < ApplicationController
def index
#posts = Post.all.order(created_at: :desc)
#comment = Comment.new
#comments = Comment.all
end
end

I think it is due to html structure or your post have only 1 comment. Try this
<div class="dropdown">
<button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">Comments
<span class="caret"></span></button>
<ul class="dropdown-menu">
<% #comments.each do |z| %>
<li><%= z.body %></li>
<% end %>
</ul>
</div>
The reason is I think in your controller you might have fatched post and its related comments (post.comments), so you do not need to check for the post.
Update:
As you have updated your question you should change your controller as well.
Post.include(:comments).all.order(created_at: :desc)
Within your partial instead of #comments use post.comments It will work perfectly. Reason of doing this is performance issue. Notice now you are making a single query and saved condition check within look. Now take eg that you have 1000 post. You will iterate over 1000 post and each post have 1000 comments it will check for all? It doesn't make any sense.

Related

List only the last 5 articles seen by current user?

I am following this stackoverflow post, How can i store and show only the last 5 NEWS seen by the current user?
However, i think I am getting this error (Couldn't find Article with 'id'=python-0), because I'm using friendly_id gem to generate the article url. Is there a workaround for this?
Application controller
before_action :recently_viewed_articles
def recently_viewed_articles
session[:article_id] ||= []
session[:article_id] << params[:id] unless params[:id].nil?
session[:article_id].delete_at(0) if session[:article_id].size >= 5
end
Pages Controller
def home
#recent_articles = session[:article_id]
#feed = current_user.feed
end
_feed.html.erb
<div class = "container">
<div class = "row">
<div class = "col-md-9">
<%= render #feed %>
</div>
<div class = "col-md-3">
<div class="list-group">
<button type="button" class="list-group-item list-group-item-action active">
Recently visited
</button>
<% #recent_articles.each do |recent| %>
<button type="button" class="list-group-item list-group-item-action">
<%= link_to "#{Article.find(recent).title}", article_path(Article.find(recent)) %>
</button>
<% end %>
</div>
</div>
</div>
</div>
As per documentation, I believe you should be using friendly scope.
Article.friendly.find(recent)
https://github.com/norman/friendly_id
Have you set everything up as you should do? If you haven't, then you can use:
Article.friendly.find('python-0')
Otherwise, in your article model:
friendly_id :title, use: [:slugged, :finders]
Then you can call
Article.find('python-0')

undefined method 'each' when accessing articles from navbar in rails app

I need to be able to access articles through the navbar dropdown.
in my views/application/_navbar.html.erbI have the code snipped below. It is not working and I always get this error undefined method 'each' for nil:NilClass
when I hit the link in the dropdown the app goes to the right path http://localhost:3000/lcas/1
I only need to be able to access the first article in each category so http://localhost:3000/lcas/1 is the right path for the first link in the dropdown
code from views/application/_navbar.html.erb
<ul class="dropdown-menu">
<% #lcas.each do |lca| %>
<li><%= link_to lca.title, lca_path(lca) %></li>
<% end %>
<% #energy_analyses.each do |energy_analysis| %>
<li><%=link_to energy_analysis.title, energy_analysis_path(energy_analysis) %></li>
<% end %>
<% #green_accountings.each do |green_accounting| %>
<li><%= link_to green_accounting.title, green_accounting_path(green_accounting) %></li>
<% end %>
<li class="divider"></li>
<li>Something</li>
<li class="divider"></li>
<li>something</li>
</ul>
On my index.html.erbI have basically the same code and there it works.
<% #lcas.each do |lca| %>
<div class="col-md-4 col-xs-12">
<span class="glyphicon glyphicon-tasks icons" aria-hidden="true"> </span>
<div class="panel-heading">
<h3 class="panel-title"><%= link_to lca.title, lca_path(lca) %></h3>
</div>
</div>
<% end %>
I've tried to add
#lcas = Lca.all
#energy_analyses = EnergyAnalysis.all
#green_accountings = GreenAccounting.all
to the application_controller.rb but with out any success.
here is the lcas_controller.rb
class LcasController < InheritedResources::Base
private
def lca_params
params.require(:lca).permit(:title, :body, :image)
end
end
It would be very nice if someone could guide me through this.
You probably need few things:
Set a before_action method for those variables in application_controller.rb to make sure each other controller calls it and pass the variable to their corresponding view:
before_action :set_vars
def set_vars
#lcas = Lca.all
#energy_analyses = EnergyAnalysis.all
#green_accountings = GreenAccounting.all
end
Now you should be able to access #lcas from your partial, but using instance variables in partials is violating MVC, so you should pass locals to it:
<%= render 'application/navbar', :lcas => #lcas %>
Not sure how to pass multiple locals, maybe like this:
<%= render 'shared/navbar', locals: {:lcas => #lcas, :energy => #energy_analyses, :green => #green_accountings} %>
And of course, don't use # in partial if passing locals:
<% energy.each do |energy_analysis| %>

change SQL limit

This comes up when I try to load from an array in my Terminal:
Site Load (0.1ms) SELECT "sites".* FROM "sites" WHERE "sites"."user_id" = ? LIMIT 1
I want to change the limit from 1 so that I can show multiple things in my ERB file.
This is how I'm trying to show them in my ERB file.
<% if #sites.is_a? Array %>
<% #sites.take(8).each do |site| %>
<!-- list to make things inline -->
<ul class="site_tab">
<li>
<%=site.text%>
</li>
<li>
<a href="/delete_site?site_id=<%= site.id %>">
<img class="delete_button" src="https://cdn4.iconfinder.com/data/icons/geomicons/32/672366-x-128.png"/>
</a>
</li>
</ul>
<% end %>
<% elsif #sites.is_a? Site %>
<% #sites.take(8).each do |site| %>
<!-- list to make things inline -->
<ul class="site_tab">
<li>
<%= site.text %>
</li>
<li>
<a href="/delete_site?site_id=<%= site.id %>">
<img class="delete_button" src="https://cdn4.iconfinder.com/data/icons/geomicons/32/672366-x-128.png"/>
</a>
</li>
</ul>
<%end%>
<% else %>
<h2>No sites to display</h2>
<% end %>
How do I change the limit? .take hasn't worked and .limit hasnt worked
I'm guessing the problem is in your controller, not your view. You probably have something like
#sites = Site.find_by user_id: current_user.id
or
#sites = current_user.sites.first
Note in both cases #sites will be a single Site, not an array. This would produce an array though:
#sites = current_user.sites.limit(1)
Also btw in your elsif #sites.is_a? Site, saying #sites.take(8).each doesn't make sense because it's not an array.

Navigation bar works on first link, but when other links are clicked items disappear

I am trying to list out a side navigation bar. The navigation should say video, followed by step 1, step 2, and step 3. It works and displays properly, but strangely, once I go to step 1 from video it instead says step 0, step 1, step 2, and step 3. When I go to the step 3 - nothing is displayed. Something is wrong with my code below, and any help would be appreciated.
<% #step_list.each_with_index do |step, i| %>
<% case step.media_type %>
<% when 'video' %>
<li class="active">
<span class="glow"></span>
<a href="<%= i %>">
<i class='icon-info-sign icon-2x'></i>
<span>Video</span>
</a>
</li>
<% when 'excel' %>
<li class="">
<span class="glow"></span>
<a href="<%= i %>">
<i class="<%= icon[i] %> icon-2x"></i>
<span>Step <%= i %> </span>
</a>
</li>
<% else %>
<li class="dark-nav ">
<span class="glow"></span>
<a href="<%= i %>">
<i class="<%= icon[i] %> icon-2x"></i>
<span>Step <%= i %></span>
</a>
</li>
<% end %>
<% end %>
Here is my steps controller
class StepsController < ApplicationController
def show
#level = Level.find(params[:id])
#step = Step.find(params[:id])
#step_list = #level.steps
end
end
The params are Parameters: {"course_id"=>"1", "level_id"=>"1", "id"=>"1"}, so you should update this line of the show action to be: #level = Level.find(params[:level_id]).
Here is how you can debug this issue.
Controller:
def show
#level = Level.find(params[:id])
#step = Step.find(params[:id])
#step_list = #level.steps
puts "**************************************"
puts "VALUE OF #step_list in controller"
puts #step_list
end
If you cannot solve your problem after inspecting #step_list, paste the #step_list value in your question and I will see if I can figure out what is going on :)
It might be step.media_type which is not giving you 'Video' and always falling into the 'else' block.

Dynamically add active class to bootstrap li in Rails

in the bootstrap navigation bar. You can get the effect of a button being clicked by adding the class active . Naturally, I want to use this on my pages. For example if I'm on the about us page I want the about us button clicked.
What is the best way to go about this? I was going to go to each page and at the bottom have a jQuery function add the class active to it. Is there a better way?
Read about current_page? here
You can add a method for handle logic with current_page?, example a method :
module ApplicationHelper
def active_class(link_path)
current_page?(link_path) ? "active" : ""
end
end
example bootstrap navbar template
<div class="navbar">
<div class="navbar-inner">
<a class="brand" href="#">Title</a>
<ul class="nav">
<li class="active">Home</li>
<li>Link</li>
<li>Link</li>
</ul>
</div>
</div>
So, on view looks like
HTML
<li class="<%= active_class(some_path) %>">
<%= link_to "text of link", some_path %>
</li>
HAML
%li{:class => active_class(some_path)}
= link_to "text of link", some_path
Or you can use request.fullpath to get current full of path if a current path have a parameter
example
<ul>
<% Contry.all.each do |c| %>
<li class="snavitem <%= active_class(contry_path(c)) %>">
<%= link_to "show #{c.name}", contry_path(c) %>
</li>
<% end %>
</ul>
and on your application_helper.rb
def active_class(link_path)
request.fullpath == link_path ? "active" : ""
end
read about request.fullpath here
in my opinion, a cleaner way to achieve that is to write a link_to_in_li method in application_helper.rb:
def link_to_in_li(body, url, html_options = {})
active = "active" if current_page?(url)
content_tag :li, class: active do
link_to body, url, html_options
end
end
then use it this way
<%= link_to_in_li "Home", root_path, id: "home_link" %>
I find the code inside li a little difficult to read.
For anyone having trouble making sense of this, here is an example with my paths and filenames laid out explicitly. As a pretty new person to rails, I was having trouble figuring it out. Thanks to the other people who answered above, as it helped me figure it out!
I placed the Bootstrap navbar in my application.html.erb file:
<div class="navbar-header">
<a class="navbar-brand" href="/">Mapper</a>
<ul class="nav navbar-nav">
<li class="<%= is_active?('/') %>"><%= link_to "Home", '/' %></li>
<li class="<%= is_active?('/main/map') %>"><%= link_to "Map", '/main/map' %></li>
<li class="<%= is_active?('/main/about') %>"><%= link_to "About", '/main/about' %></li>
</ul>
</div>
This goes in the application_helper.rb file:
module ApplicationHelper
def is_active?(link_path)
current_page?(link_path) ? "active" : ""
end
end
That's it! Now your application will dynamically add the 'active' class to whatever page is currently being viewed (i.e. it's corresponding list item in the navbar). This is much simpler (and more DRY) than adding the navbar manually to each page (view) and then updating the 'active' class.
I'll post my answer that I created based on these others because in case of CRUD views the active class wasn't been placed.
module ApplicationHelper
def active_class(name)
controller_name.eql?(name) || current_page?(name) ? 'active' : ''
end
end
My views use something like this:
<ul class="nav navbar-nav">
<li class="nav-item <%= active_class('/') %>">
<a class="nav-link" href="/">Home</a>
</li>
<li class="nav-item <%= active_class('leads') %>">
<a class="nav-link" href="/leads">Leads</a>
</li>
</ul>
<ul class="nav navbar-nav pull-right <%= active_class(edit_user_registration_path) %>">
<li class="nav-item ">
<a class="nav-link" href="/users/edit">Perfil</a>
</li>
<li class="nav-item">
<%= link_to('Sair', destroy_user_session_path, method: :delete) %>
</li>
</ul>
Please try this in each page, check the cotroller or action and add the css
For example:
<li class= <%= (controller.controller_name.eql?('pages') && controller.action_name.eql?('index') )? 'active':''%> ><%= link_to 'my page', pages_path%></li>
You may define a helper method in application_helper.rb
def create_link(text, path)
class_name = current_page?(path) ? 'active' : ''
content_tag(:li, class: class_name) do
link_to text, path
end
end
Now you can use like:
create_link 'xyz', any_path which would render as <li class="active">xyz</li>
Perfect for bootstrap navigation!
Why limit yourself to only li elements? And why not support multiple class names along with active? This solution lets me:
Support not only plain text but HTML inside link_to (e.g. add an icon inside the link)
Add just few lines of code to application_helper.rb
Append active to the whole class name of the link element instead of it being the sole class.
So, add this to application_helper.rb:
def active_class?(class_name = nil, path)
class_name ||= ""
class_name += " active" if current_page?(path)
class_name.strip!
return class_name
end
And on your template you can have something like this:
<div class="col-xs-3">
<%= link_to root_path, :class => active_class?("btn btn-outline-primary", root_path) do %>
<i class="fa fa-list-alt fa-fw"></i>
<% end %>
</div>
You can also specify or not a class_name and use it like this:
<li class="<%= active_class?(root_path) %>">Home</li>
Thanks to previous answers 1, 2 and resources.

Resources