0
votes

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>
1
You have to add creating that variable into the home controller index method. If you look in the method for plants there is likely this, @plants = Plant.all, right? Put that inside the home controller index method and you will have created the variable so you can use it. Just to be clear you do not"import" it. You have to create the variable in order to use it, and each page has a method, and inside that method you can create any variable to use in the view.Rockwell Rice
Thank you, this was perfect. Why didn't you answer instead of commenting, so I could check it as the correct answer?cratag
Well without code I couldn't really provide an actual answer so I just explained to you what was going on. Plus, I am sure this has been answered somewhere on here previously. Hope it makes sense going forward on that.Rockwell Rice

1 Answers

1
votes

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.