5

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 methodeach' for nil:NilClasson 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

2
  • In which action do you want worker category? Commented Oct 14, 2015 at 10:13
  • well that's the problem. there isn't any action, i want it in the application.html.erb. I've looked around for some other topics like these suggesting using a before_filter. but that didn't work out. So now i'm stuck ... Commented Oct 14, 2015 at 10:15

4 Answers 4

7

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

Sign up to request clarification or add additional context in comments.

5 Comments

This gave me 'undefined method `first' for nil:NilClass'. I've removed that line and got back to nil class. etc ... i'm thinking i'm maybe not saving it right or something....
I added the change.Just as a confirmation, do you have data in Workcategory model?
hey yes thanks for the unless. I've tried it, and although it doesn't work like i want it. Now i/we know that the work category isn't saved correctly. When i go to rails console and check, i have 3 work categories but they just don't show ... and i've tried the before_filter and still doesn't. any ideas ?
@alexlug, try better_errors gem for dynamic debugging
ha in the end it was a mix between your answer and Rich's :) now it works, thank you !!
2

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

4 Comments

this is giving me the same error. I actually tried 'workcategories' before and it wasn't working :) so the issue is somewhere else. thank you.
hey i've already tried this second option, the update. And this didn't work either. i'm getting the same error.
@alexlug, please update the answer with the exact code you tried (including this before_action)
In the end i went for this => before_action :work_categories private def work_categories @workcategory = Workcategory.all.order("created_at DESC") end. Now that i think about it you did post an alright version, but me being a total beginner i didn't know what was up and failed to use it correctly.
2

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

enter image description here

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.

1 Comment

thank you .. this was the missing piece, that before_action combined with Amit's code ! Thank you !
0

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>

4 Comments

hello. I've tried this and it threw : undefined method `helper_method' for main:Object
Did you add the code to apps/controllers/application_controller.rb ?
The method needs to be defined within the ApplicationController code. I've modified my answer to show this.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.