Changing an element styles given a string pattern in Rails - ruby-on-rails

What to change give an active class to a li depending of the route.
I have this routes:
/profile/2
/profile/2/info
/profile/2/contact
I have a menu
<ul>
<li>
<%= link_to 'Profile', profile_path(current_user), class: current_class_contains?('/profiles') %>
</li>
<li>
<%= link_to 'Info', info_profile_path(current_user), class: current_class_contains?('/info') %>
</li>
<li>
<%= link_to 'Contact', contact_profile_path(current_user), class: current_class_contains?('/contact') %>
</li>
</ul>
In application_helper
module ApplicationHelper
def current_class_contains?(test_path)
return "active" if request.path.match(test_path)
""
end
def current_class?(test_path)
return "active" if request.path == test_path
""
end
end
The problem that I got is that if I'm in /profile/2/info or /profile/2/contact the Profile li is also given the active class.
I can't figure it out. Any ideas?

Use current_page?, Something like following
return "active" if current_page? test_path
& calling
current_class_contains?(profile_path(current_user))

I would use current_page? to build a helper method like this:
def indicating_link_to(name, url)
css_class = 'active' if current_page?(url)
link_to(name, url, class: css_class)
end
And use that helper method like this in your view:
<ul>
<li>
<%= indicating_link_to 'Profile', profile_path(current_user) %>
</li>
<li>
<%= indicating_link_to 'Info', info_profile_path(current_user) %>
</li>
<li>
<%= indicating_link_to 'Contact', contact_profile_path(current_user) %>
</li>
</ul>
And with the new class_names method that will be introduced with Ruby on Rails 6.1 it will be even simpler:
def indicating_link_to(name, url)
link_to(name, url, class: class_names(active: current_page?(url)))
end

Related

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

How build a breadcrumbs in rails 4

Seriously, I have no idea where to start. How do I implement a helper breadcrums without using gems?
I tried some gems, but I preffer make a simple helpe. Exist someone or some tutorial? I not found this =/
Thanks!
My solution:
navigation_helper.rb
module NavigationHelper
def ensure_navigation
#navigation ||= [ { :title => 'Home', :url => '/' } ]
end
def navigation_add(title, url)
ensure_navigation << { :title => title, :url => url }
end
def render_navigation
render :partial => 'navigation', :locals => { :nav => ensure_navigation }
end
end
_navigation.html.erb
<ol class="breadcrumb">
<% nav.each do |n| %>
<% unless n.equal? nav.last %>
<li><%= link_to n[:title], n[:url] %></li>
<% else %>
<li><%= n[:title] %></li>
<% end %>
<% end %>
</ol>
application.html.erb
<%= render_navigation %>
And any view:
<% content_for :title, 'My Page Title' %>
<% navigation_add #something.anything, '#' %>
You cant do this.
In your application_helper:
def breadcrumb(&block)
content_tag :ol, { :class => "breadcrumb", :itemprop => "breadcrumb" } do
block.call
end
end
def breadcrumb_item(name = nil, url = nil, html_options = {}, &block)
if name or block
html_options[:class] = "#{html_options[:class]} active" unless url
content_tag :li, html_options do
if block
block.call name, url
else
url ? link_to(name, url) : name
end
end
end
end
Now in views you paste this: (I used index_path and #user.name) - you can paste this code on show view as an example
<%= breadcrumb do %>
<%= breadcrumb_item "index", index_path %>
<%= breadcrumb_item #user.name %>
<% end %>
Now when you need some breadcrumb you can just call this trunck above and change the path and the instance variables #your_variable
I further worked on Elton Santos's solution and decided breadcrumbs should be automatic like history. So I modified some code:
In my application.html.erb
<%= render_navigation %>
In my views, I was already using:
<% content_for :heading do 'User Detail' end %>
So, my navigation_helper.rb look like:
module NavigationHelper
def navigation_add(title, url)
nav_list = session['navigation'].present? ? session['navigation'] : []
nav_list << { 'title' => title, 'url' => url }
# 1. Take last 3 items only (-1 is last, not -0)
nav_list = nav_list[-3..-1] if nav_list.length > 3
# 2. Now, if first is pointing root, remove it
nav_list.shift if nav_list[0]['url'] == '/'
# 3. If last one is same as its predecessor, remove it
nav_list.pop if nav_list.length > 1 && (nav_list[-1]['url'] == nav_list[-2]['url'])
session['navigation'] = nav_list
end
def render_navigation
render partial: 'shared/navigation', locals: { nav_list: session['navigation'] }
end
end
and finally, _navigation.html.erb:
<ol class="breadcrumb">
<li><%= link_to '/' do %>
<i class="fa fa-home"></i> Home <% end %>
</li>
<i class="fa fa-angle-double-right" style="color: #ccc; padding: 0 5px;"></i>
<% nav_list.each_with_index do |nav, i| %>
<% if i != nav_list.length-1 %>
<li><%= link_to nav['title'], nav['url'] %></li>
<% else %>
<li class="active"><%= nav['title'] %></li>
<% end %>
<% end %>
</ol>
So, what's going up here is; I save every page title in session and build breadcrumbs from that. I keep recent three entries only along with hard-coded one for Home and remove duplicate entries when they are not apart.

Refactor simple rails code for specifying active li on navigation

I am trying to set an li class of active based on what page the user is on.
I have 4 navigation elements and they all look something like this:
<% if #activeLi == "home" %>
<li class="active">
<% else %>
<li>
<% end %>
<%= link_to :controller => "home" do %>
<span>Home</span>
<% end %>
</li>
and then in each controller I just set #activeLi like this:
def index
#activeLi = "about"
end
I know this is pretty basic stuff, but i'm just wondering if there is an easier way to do this?
Well I know one way you can simplify this and thats by getting rid of the need to use those nasty instance variables.
<li class="<%= controller_name == "home" ? 'active': '' %>">
<%= link_to :controller => "home" do %>
<span>Home</span>
<% end %>
</li>

Add a class to anchor with li class already "current"

I have been Trying to figure this out for some time now. I have a navigation where the list item gets a class of "active" when on that page. I need to also give the anchor of those list items each a unique class. So my code is:
Application_helper
def link_to_with_current_class(name, options)
if current_page?(options)
content_tag :li, link_to(h(name), options), :class => "current"
else
content_tag :li, link_to(h(name), options)
end
end
Navigation
<ul id="nav">
<%= link_to_with_current_class "work", home_path %>
<%= link_to_with_current_class "about", about_path %>
<%= link_to_with_current_class "contact", contact_path %>
</ul>
This Generates
<ul id="nav">
<li class="current">work</li>
<li>about</li>
<li>contact</li>
</ul>
I need it to generate
<ul id="nav">
<li class="current"><a **class="work"** href="/">work</a></li>
<li><a **class="about"** href="/about">about</a></li>
<li><a **class="contact"** href="/contact">contact</a></li>
</ul>
I have tried this many ways but everything i try just breaks it. Any help on this issue would be much appreceatied.
This looks like it might work:
def link_to_with_current_class(name, options)
if current_page?(options)
content_tag :li, link_to(h(name), options, :class => name), :class => "current"
else
content_tag :li, link_to(h(name), options, :class => name)
end
end

Ruby on rails and tabs

I'm still a beginner with ruby and rails, and now I'm googling about methods for creating a tabbed menu, marking the list element of the currently active controller with a css class "current". There are many hits on google, but I haven't found any that I manage to get working.
I have my menu here:
<ul>
<li class="current"><%= link_to 'Home', root_path %> </li>
<li><%= link_to 'Browse songs', page_path('browse') %> </li>
<li><%= link_to 'Add song', new_song_path %> </li>
<li><%= link_to 'Request song', artists_path %> </li>
<li><%= link_to 'My ReChord', artists_path %> </li>
<li><%= link_to 'Help', page_path('help') %> </li>
<li id="search"><form><input type="search" placeholder="Type here to find a song or an artist"/></form> </li>
<li class="notab">
<% if user_signed_in? %>
<%= link_to 'Sign out', destroy_user_session_path %>
<% else %>
<%= link_to 'Sign in', new_user_session_path %> or
<%= link_to 'sign up', new_user_registration_path %>
<% end %>
</li>
</ul>
Now I have class="current" hard coded on the Home tab. However, when clicking for example Browse songs, I want the class="current" to be moved to the corresponding list element for that line.
Note that I have some links that just is the route path (like new_song_path) and some links that are sub pages, like page_path('help'). I need it to work for both these types of links.
Can you provide me with either a good tutorial suitable for my two days long experience with rails, or (preferably) example code that might fit perfectly on my list above? Thanks in advance!
Create a helper to build that menu for you:
def menu_builder(page_id)
tabs = ['home','store','faq']
content = ""
tabs.each do |tab|
content << if page_id == tab
content_tag('li', content_tag('a', tab, :href => nil ), :class => 'current') + " "
else
content_tag('li', content_tag('a', tab, :href => "/#{tab}" )) + " "
end
end
content
end
Or my own short version of it:
def menu_builder(page_id)
["home", "store", "faq"].map { |tab|
%{<li class="#{page_id == tab ? "active" : "inactive"}">#{tab.capitalize}</li>}
}.join("\n")
end
page_id is an identifier of some page and should be defined in your controllers.
class Foo < ApplicationController
def faq
#page_id = 'faq'
...
end
end
Then just use it in the template:
<ul>
<%= menu_builder(#page_id) %>
<li class="search">...</li>
</ul>
If you want something more flexible, checkout the tabs_on_rails plugin I created to solve exactly this common pattern.
In your template use the tabs_tag helper to create your tab.
<% tabs_tag do |tab| %>
<%= tab.home 'Homepage', root_path %>
<%= tab.dashboard 'Dashboard', dashboard_path %>
<%= tab.account 'Account', account_path %>
<% end %>
The example above produces the following HTML output.
<ul>
<li>Homepage</li>
<li>Dashboard</li>
<li>Account</li>
</ul>
The usage is similar to the Rails route file. You create named tabs with the syntax tab.name_of_tab.
The name you use creating a tab is the same you’re going to refer to in your controller when you want to mark a tab as the current tab.
class DashboardController < ApplicationController
set_tab :dashboard
end
Now, if the action belongs to DashboardController, the template will automatically render the following HTML code.
<ul>
<li>Homepage</li>
<li class="custom"><span>Dashboard</span></li>
<li>Account</li>
</ul>
Take a look an this plugin:
http://github.com/paolodona/rails-widgets
It has lots of cool components including navigation.
Documentation: https://github.com/paolodona/rails-widgets/wiki
I created tabulous to solve this problem. There is a separate tab configuration file where you can describe how you want your tabs to behave. For example:
Tabulous.setup do
tabs do
pictures_tab do
text { 'Pictures' }
link_path { pictures_path }
visible_when { true }
enabled_when { true }
active_when { in_action('any').of_controller('pictures') }
end
music_tab do
text { 'Music' }
link_path { songs_path }
visible_when { true }
enabled_when { current_user.has_music? }
active_when { in_action('any').of_controller('songs') }
end
profile_tab do
text { 'My Profile' }
link_path { account_path(current_user) }
visible_when { true }
enabled_when { true }
active_when { in_actions('show', 'edit', 'update').of_controller('accounts') }
end
end
end
Read the tabulous documentation to learn more.

Resources