Reputation: 1449
I was practising one of tutorials from a book. In this tutorial; all values from a few models were needed to be shown in some views. These instance variables were defined under sidebar_values
method in application_controller.rb
:
helper_method :sidebar_values
def sidebar_values
@food_prefs = FoodPreference.all
@food_types = FoodType.all
@cuisines = Cuisine.all
end
Here is the part of the application.html.erb
:
<div class="col-lg-2">
<div class="panel panel-primary" id="panels">
<div class="panel-heading">
Food Preferences
</div>
<% @food_prefs.each do |p| %> #42, error begins here
<p><%= p.name %></p>
<% end %>
</div>
<div class="panel panel-primary" id="panels">
<div class="panel-heading">
Food Types
</div>
<% @food_types.each do |t| %>
<p><%= t.name %></p>
<% end %>
</div>
<div class="panel panel-primary" id="panels">
<div class="panel-heading">
Cuisines
</div>
<% @cuisines.each do |c| %>
<p><%= c.name %></p>
<% end %>
</div>
</div>
When I was trying to call these variables in a view, it throws error like this:
NoMethodError - undefined method `each' for nil:NilClass:
app/views/layouts/application.html.erb:42:in `_app_views_layouts_application_html_erb___4138475832854219665_70001190164060'
Values in these variables aren't nil
, however I was unable to call these variables from any view.
Upvotes: 0
Views: 1203
Reputation: 2508
The reason why you are getting undefined method 'each' for nil:NilClass:
on <% @food_prefs.each do |p| %>
is because @food_prefs
variable is nil. you are calling a method: each
on a nil variable: @food_prefs
. basically, if you open a rails console
and query FoodPreference.count
, it would return zero
count. To get past this, create an instance of this class in the database so your count is no longer zero.
Or:
wrap around it an if statement. something like this:
<% if @food_prefs %>
<% @food_prefs.each do |p| %>
<p><%= p.name %></p>
<% end %>
<% end %>
you can remove this if statement
later when you are sure your @food_prefs
is no longer nil
How to define variables in a helper method:
though you may not need to define helper method in this case, you define them inside the files in your Helper
folder. it's a straight forward ruby. just create methods that you can call inside your views. unlike the controller methods, you don't need the @
symbol. methods created inside your helpers
are available in your views.
Upvotes: 0
Reputation: 54882
I know you are following a tutorial, but I think there is something missing:
# application_controller.rb
before_filter :sidebar_values
def sidebar_values
@food_prefs = FoodPreference.all
@food_types = FoodType.all
@cuisines = Cuisine.all
end
This before_filter :sidebar_values
will call the method sidebar_values
on each action called. You can specify only/except options to filter a little bit the affected actions:
before_filter :sidebar_values, except: [:login, :logout]
Also, I would use a better name for this method, something like set_sidebar_variables
since it is setting instance variables for the sidebar.
As I explained in the comments, I don't think you need to make it a helper method, IMO helper_method :sidebar_values
can be removed.
Another thing is that there is not limit on your SQL queries, you just query all of the 3 models. This is not good in long-term. What if you have hundreds of Cuisines, FoodTypes and FoodPrefs ? I would add a .limit(x)
to prevent from this case to happen:
def sidebar_values
@food_prefs = FoodPreference.limit(10)
@food_types = FoodType.limit(10)
@cuisines = Cuisine.all
end
Upvotes: 3