I'm trying to create a sidebar menu with the below information:
# app/controllers/users_controller.rb
def show
@user = User.friendly.find(params[:id])
end
# config/routes.rb
get "/user/:id", to: "users#show"
I have the link from the dropdown menu to the current_user
path:
<!-- app/views/layouts/_dropdown_menu.html.erb -->
<%= link_to "My Account", current_user %>
This is how I create the sidebar menu:
<!-- app/views/layouts/dashboard.html.erb -->
<%= render "shared/sidebar_panel" %>
<!-- app/views/shared/_sidebar_panel.html.erb -->
<%= render "shared/nav" %>
<!-- app/views/shared/_nav.html.erb -->
<% SidebarMenu.all.each do |entry| %>
<% if entry[:group_title].present? %>
<li ><%= entry[:group_title]%></li>
<% end %>
<%= render partial: 'shared/nav_submenu',
collection: entry[:children],
as: :sub_menu,
locals: {parents: []} %>
<% end %>
<!-- app/views/shared/_nav_submenu.html.erb -->
<li>
<a href="<%= sub_menu[:href] %>">
<span><%= sub_menu[:title] %></span>
<% if sub_menu[:subtitle].present? %>
<span >
<%= sub_menu[:subtitle] %>
</span>
<% end %>
</a>
<% if sub_menu[:children].present? %>
<ul>
<%= render partial: 'shared/nav_submenu',
collection: sub_menu[:children],
as: :sub_menu,
locals: {parents: parents [sub_menu]} %>
</ul>
<% end %>
</li>
I have a SidebarMenu
model and I've added current_user
path:
# app/models/sidebar_menu.rb
class SidebarMenu
class << self
include Rails.application.routes.url_helpers
end
def self.all
[
{
group_title: "Account & Contact",
children: [
{
href: "#",
title: "Account",
icon: "...",
children: [
{
href: current_user,
title: "My Account"
}
]
},
# ...
]
}
]
end
end
But it raises an error message:
undefined local variable or method `current_user' for SidebarMenu:Class
Can anyone advise me how I can fix this?
CodePudding user response:
This is how current_user
method is set up by Devise: current_user is a controller method included by devise and loaded in ActionController::Base
class. It is also available in the views because it is a helper method which gets included in ActionView::Base
. current_user
is not a url helper and it returns a User
model instance which link_to
can turn into a url automatically.
current_user
is outside of the scope of SidebarMenu
class. To fix it, just pass it as an argument:
class SidebarMenu
def self.all user
[{ href: user, title: "My Account" }]
end
end
# in the view or controller
SidebarMenu.all(current_user) # => [{ href: #<User:0x0000563cc7c69198>, title: "My Account" }]
I think, a better approach is to use menu class as an object. It is more flexible and easier to use:
class Menu
include Rails.application.routes.url_helpers
def initialize(user:)
@user = user
end
def user_menu
{
group_title: "Account",
# NOTE: use url helper to return a path instead of a `User` model
children: [{ href: user_path(user), title: "My Account" }]
}
end
def sidebar_menu
{
group_title: "Main",
children: [{ href: root_path, title: "Home" }]
}
end
def all
[sidebar_menu, user_menu]
end
private
attr_reader :user
end
Use it in the view:
Menu.new(user: current_user).user_menu[:children]
# => [{ href: "/users/1", title: "My Account" }]
You can also set up a helper method:
# in the ApplicationController
private
def menu
@menu ||= Menu.new(user: current_user)
end
helper_method :menu
# in the view
menu.user_menu[:children] # => [{ href: "/users/1", title: "My Account" }]
# TODO:
# menu.sidebar_menu
# menu.all.each do |group|
# group[:group_title]
# ...
# end
https://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to
List url helpers: Rails.application.routes.named_routes.helper_names
List controller helpers: ApplicationController._helper_methods