Reputation: 122
I have generated a Scaffold in rails which has some information about some plants: name, description. id.
I want to show that information in my root "home#index"
but the index page doesn't render and I get the error:
NoMethodError in Home#index
undefined method `each' for nil:NilClass
<% @plants.each do |plant| %>
this is my code
I know it's not "importing" my @plants class, so how can I get it imported into different views?
<table class="table">
<tbody>
<% @plants.each do |plant| %>
<tr>
<td><%= plant.plant_name %></td>
<td><%= plant.plant_description %></td>
<td><%= plant.plant_id %></td>
</tr>
<% end %>
</tbody>
</table>
Upvotes: 0
Views: 126
Reputation: 102250
You have got the concepts all wrong here. The Rails scaffold command sets up a model, controller and views. The scaffolding command does not set up any data. You would setup data by using the rails db:seed
command. @plants
is not a class - its just an instance variable that the scaffold will assign to Plant.all
.
In Ruby you can reference an instance variable even if it has not been defined and simply get nil. But when you call @plants.each do |plant|
you get an error since you're calling #each
on nil. This one the key gotchas in Ruby which tends to trip up both beginners and sometimes even experienced developers.
In Rails each request is matched by the router to a controller and action (a method on the controller). If you want to display a list of the plants on your HomeController
you need to assign that instance variable:
class HomeController < ApplicationController
def index
@plants = Plant.all
end
end
Rails then "provides" all the instance variables of the controller to the view - this is known as the view context.
If you want to share code between your HomeController and PlantController you would use a module:
module Planted
extend ActiveSupport::Concern
included do
before_action :set_plants, only: [:index]
end
def set_plants
@plants = Plant.all
end
end
class PlantsController < ApplicationController
include Planted
# ...
end
class HomeController < ApplicationController
include Planted
# ...
end
Or inheritance if it passes the liskov substitutability principle.
If you want to share view code use partials.
Upvotes: 1