简体   繁体   中英

Using a controller variable in application html.erb

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM