I'm probably trying too hard for my first website but i wanted to make a dropdown on a (bootstrap) navbar to be flexible, and show the names of the saved work categories.
This is what i've tried to do in the application.html.erb file :
<ul class="dropdown-menu">
<% @workcategory.each do |workcategory| %>
<li><%= workcategory.name%></li>
<% end %>
Failed with error undefined method
each' for nil:NilClass on the
<% @workcategory.each do |workcategory| %>` line.
This is the workcategories controller :
class WorkcategoriesController < ApplicationController
before_action :find_workcategory, only: [:edit, :update, :destroy]
def index
@workcategories = Workcategory.all.order("created_at DESC")
end
def new
@workcategory = Workcategory.new
end
def create
@workcategory = Workcategory.new(post_params)
if @workcategory.save
flash[:notice] = "Workcategory created"
redirect_to(:action=>'index', :workcategory_id => @workcategory.id)
else
@workcategories = Workcategories.order()
render('new')
end
end
def edit
end
def update
end
def destroy
@workcategory.destroy
redirect_to workcategory_path
end
private
def find_workcategory
@workcategory=Workcategory.find(params[:id])
end
def post_params
params.require(:workcategory).permit(:name)
end
end
Any tips and help are welcome, even non-related to the initial question :) Thank you
If you want it in all ur actions, it is wise to put it in your application_controller.rb
.
before_filter :set_work_categories
def set_work_categoriers
@w_categories = Workcategory.all.order("created_at DESC")
end
This should work fine.
Also, a tip.
You can use default_scope {order(created_at: :desc)}
in your model WorkCategory.rb
Then you can use this like,
def set_work_categoriers
@w_categories = Workcategory.all
end
I would recommend changing the variable name to @w_categories or else it will conflict with your @work_categories name in index
action.
In your application.html.erb
file, change
<% unless @w_categories.nil? %>
<ul class="dropdown-menu">
<% @w_categories.each do |workcategory| %>
<li><%= workcategory.name%></li>
<% end %>
</ul>
<%end>
I guess this should do the trick
If we talk about index
action, then you just forgot to use appropriate variable:
<ul class="dropdown-menu">
<% @workcategories.each do |workcategory| %>
<li><%= workcategory.name%></li>
<% end %>
Update
If you want to have this in all actions, then initialize @workcategories
in before_action
:
# your_controller.rb
before_action :initialize_work_categories
def initialize_work_categories
@workcategories = Workcategory.all.order("created_at DESC")
end
Layouts
application.html.erb
is a layout , meaning that it will be present regardless of whether you're using the Workcategories
controller or not.
If you want to load a variable into the layout , irrespective of which controller is being invoked, you'll need to make sure the @workcategory
variable is present.
To do this, you would generally put the @workcategory
declaration into the ApplicationController
(which most other controllers inherit from):
#app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_action :set_categories
private
def set_categories
@workcategory = ....
end
end
This is the standard way to populate layout-side variables. It's not efficient and only works if your controllers inherit from the Application
controller.
Some further pointers would include the following:
1. Object orientation
Ruby, and by virtue, Rails, is object orientated .
This means that everything you do should revolve around objects . This is why Rails has many helpers that seem to work "magically".
They're not magic at all - they just take the objects you pass them, and build pre-baked HTML to give you specific functionality.
A good example are the routes :
#config/routes.rb
resources :controller
The reason this is important is that when you call actions / variables, you need to think of them as objects . This is difficult to do for newbies, but if you can get your head around it, it helps your coding massively.
--
2. Controllers
Following on from the above, you have to remember that your controller is really just a way to manipulate objects.
Thus, if you're calling @workcategory
, you need to appreciate where the object is going to come from and how it's going to be populated.
You can make a helper method work_categories and use that. Either define it directly in application_helper - or if you don't want to use helpers you can put this code in your ApplicationController
class ApplicationController < ActionController::Base
def work_categories
Workcategory.all.order("created_at DESC")
end
helper_method :work_categories
end
Then in your view:
<ul class="dropdown-menu">
<% work_categories.each do |workcategory| %>
<li><%= workcategory.name%></li>
<% end %>
</ul>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.