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.
Related
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
I want to define a string called index_title and send it from a controller to a view and insert index_title into <% provide(:title, index_title) %> at the top of my view. Is this possible?
Edit: I have a few links in a dropdown tab in my _header file such as
<li><%= link_to "All Users", users_path, :tab => 1 %></li>
<li><%= link_to "DERs", users_path, :tab => 2 %></li>
...
and in my users_controller, I have the index action as
def index
if params[:tab] == 1
#index_title = 'All Users'
#users = User.where(activated: true).paginate(page: params[:page])
elsif params[:tab] == 2
#index_title = 'DERs'
#users = User.where(activated: true, der: true).paginate(page: params[:page])
...
end
end
and my index view is
<% provide(:title, #index_title) %>
<h1><%= #index_title %></h1>
<%= will_paginate %>
<ul class="users">
<%= render #users %>
</ul>
<%= will_paginate %>
but it won't change the #users list no matter the tab and it won't change the provided title or h1 title. Any ideas?
My issue was that params[:tab] == 1 needed to be params[:tab] == '1'. The #index_title worked out fine as stated in the problem.
I got the following code in my view:
<ul class="thumbnails">
<% Photo.find_all_by_id(my_params, limit: 10).each do |p| %>
<li class="thumbnail">
<%= image_tag(p.url(:fb)) %>
</li>
<% end %>
</ul>
It renders an unordered list with thumbnails. And it works okay - I see the list with images:
<ul class="thumbnails">
<li class="thumbnail">
<img alt="bmw" src="/assets/.../bmw.jpg?1364218949">
</li>
</ul>
I would like to put it into helper, like this:
module PhotosHelper
def photos_thumbs_by_ids(photos_ids)
content_tag :ul, :class => "thumbnails" do
Photo.find_all_by_id(photos_ids, limit: 10).each do |p|
content_tag :li, :class => "thumbnail" do
image_tag(p.url(:fb))
end
end
end
end
end
But when I use <%= photos_thumbs_by_ids my_params %> in my view, it renders only:
<ul class="thumbnails"></ul>
What am I doing wrong?
The problem is the each :
Photo.find_all_by_id(photos_ids, limit: 10).each do |p|
...
end
It return an array, not the string. Try to collect it with 'map' and do a join
module PhotosHelper
def photos_thumbs_by_ids(photos_ids)
content_tag :ul, :class => "thumbnails" do
Photo.find_all_by_id(photos_ids, limit: 10).map { |p|
content_tag :li, :class => "thumbnail" do
image_tag(p.url(:fb))
end
}.join.html_safe
end
end
end
It's beacuse at least the rendering is done by the useful method capture. This method put in output buffer only if the result is a string, and don't try a to_s.
What i found after seeing your code is, you are not passing the photo_ids parameter while calling the helper method.
<%= photos_thumbs_by_ids(photo_ids) %>
As there is no ids to find photos, so it is returning zero items, so no <li> items will be created.
Try as follow;
<%= photos_thumbs_by_ids(photo_ids) %>
def photos_thumbs_by_ids(photos_ids)
content_tag :ul, :class => "thumbnails" do
Photo.find_all_by_id(photos_ids, limit: 10).each do |p|
content_tag :li, :class => "thumbnail" do
concat(image_tag(p.url(:fb)))
end
end
end
end
On every page we have a condition like this for guest user.
<% if not_guest? %>
<% link_to "show", path %>
<% end %>
<% if not_guest? %>
<% link_to "delete", path %>
<% end %>
<% if not_guest? %>
<% link_to "edit", path %>
<% end %>
for which link should appear or not for guest user.
Are there any better ways to handle this scenario instead of writing the conditions for every link ?
Make a helper:
#helpers/application_helper.rb
def link_to_unless_guest(*args)
if not_guest
link_to(*args)
end
end
Then call like
<% link_to_unless_guest "show", path %>
def link_to_editable(*args)
options = args.extract_options![:parent]
html_tag = options.nil? ? nil : options.delete(:html_tag)
if not_guest
unless html_tag.nil?
content_tag html_tag,options do
link_to(*args)
end
else
link_to(*args)
end
end
end
<%= link_to_editable 'Show', path,:parent => {:html_tag => "li",:style => "border-top:1px solid #A2A2A2;",:class => "left"} %>
<%= link_to_editable 'Show', path %>
Modified helper which is provided by #Max as per my need.
This is the error:
No route matches {:action=>"send_to_client", :controller=>"stages"}
It corresponds to this line:
<%= link_to "<span class='icon send-to-client-icon' title='Send to Client' id='send-to-client'> </span>".html_safe, send_to_client_stage_path(#stage), :id => stage.id, :confirm => "This will send #{stage.name.capitalize} to #{stage.client.email}. Are you sure you are ready?" %>
In this _show_table.html.erb
<%
if #upload != nil
stage = #upload.stage
end
%>
<h1 class="panel-header">Images</h1>
<% if stage == nil %>
<div class="images_menu">
<%= link_to "<span class='icon send-to-client-icon' title='Send to Client' id='send-to-client'> </span>".html_safe, send_to_client_stage_path(#stage), :id => stage.id, :confirm => "This will send #{stage.name.capitalize} to #{stage.client.email}. Are you sure you are ready?" %>
<span class="icon compare-icon" data-url="<%= compare_stage_path(stage)%>" title="Compare Images" id="compare-images"> </span>
</div>
<% end %>
Here is my routes.rb:
resources :stages do
member do
get :step
get :compare
get :send_to_client
end
end
The issue is that this partial _show_table.html.erb is in the view folder of my uploads model...not the stages model.
When I execute that link_to in the stages model, it works fine. Once I take it out into the uploads model it throws that error.
Why would that be the case ?
Edit1: Here is the send_to_client action of the stages controller:
def send_to_client
stage = Stage.find(params[:id])
ClientMailer.send_stage(stage).deliver
if ClientMailer.send_stage(stage).deliver
flash[:notice] = "Successfully sent to client."
redirect_to("/")
else
flash[:notice] = "There were problems, please try re-sending."
redirect_to("/")
end
end
Rails will raise an ActionController::RoutingError if you use send_to_client_stage_path(nil).
You're mixing up #stage and stage. If you don't define #stage in the controller action, it will be nil and the error raises. In this case, just use #upload.stage.
Like:
<% if #upload.stage %>
<%= link_to "...", send_to_client_stage_path(#upload.stage), :confirm => "..." %>
<% end %>
If you want to use #stage, just define it in the action with #stage = #upload.stage and use it instead of #upload.stage:
<% if #stage %>
<%= link_to "...", send_to_client_stage_path(#stage), :confirm => "..." %>
<% end %>
It should probably be
send_to_client_stage_path(stage)
instead of
send_to_client_stage_path(#stage)
And it should be "unless", not "if" here, right?
<% unless stage.nil? %>
Also, dont forget you can use "unless", it's nicer sometimes
if #upload != nil
stage = #upload.stage
end
->
stage = #upload.stage unless #upload.nil?