C.B.
C.B.

Reputation: 310

undefined method for collect error

Greetings my fellow programmers. I have 2 questions. 1 of course is how can i fix this problem. And second what does this error mean, so for my next encounter i know how to deal with it.

My _form.html.erb

<%= error_messages_for(@section) %>

  <table summary="Section form fields">
      <tr>
        <th><%= f.label(:page_id, "Page ID") %></th>
         <td><%= f.select(:page_id, @pages.collect {|p| [p.name, p.id]}) %>
      </tr>
      <tr>
        <th><%= f.label(:name) %></th>
        <td><%= f.text_field(:name) %></td>
      </tr>
      <tr>
        <th><%= f.label(:position) %></th>
        <td><%= f.text_field(:position) %></td>
      </tr>
      <tr>
        <th><%= f.label(:visible) %></th>
        <td><%= f.select(:visible, 1..@section_count) %></td>
      </tr>
      <tr>
        <th><%= f.label(:content_type) %></th>
        <td>
          <%= f.radio_button(:content_type, 'text') %> Text
          <%= f.radio_button(:content_type, 'HTML') %> HTML
        </td>
      </tr>
      <tr>
        <th><%= f.label(:content) %></th>
        <td><%= f.text_area(:content, :size => '40x10') %></td>
      </tr>
    </table>

My Section controller

class SectionsController < ApplicationController

  layout "admin"

  before_action :confirm_logged_in
  before_action :find_page

  def index
    @sections = @page.sections.sorted
  end

  def show
    @section = Section.find(params[:id])
  end

  def new
    @section = Section.new({:name => "Default", :page_id => @page.id})
    @section_count = Section.count +1
  end

  def create
    @section = Section.new(section_params)
    if @section.save
      flash[:notice] = "Section created successfully."
      redirect_to(:action => 'index', :page_id => @page.id)
    else
      @pages = @page.subject.pages.sorted
      @section_count = Section.count +1
      render('new')
    end
  end

  def edit
    @section = Section.find(params[:id])
  end

  def update
    @section = Section.find(params[:id])
    if @section.update_attributes(section_params)
      flash[:notice] = "Section updated successfully."
      redirect_to(:action => 'show', :id => @section.id, :page_id => @page.id)
    else
      @section_count = Section.count 
      render('edit')
    end
  end

  def delete
    @section = Section.find(params[:id])
  end

  def destroy
    @section = Section.find(params[:id]).destroy
    flash[:notice] = "Section destroyed successfully"
    redirect_to(:action => 'index' , :page_id => @page.id)
  end

  private

  def section_params
    params.require(:section).permit(:page_id, :name, :position, :visible, :content_type, :content)
  end

  def find_page
    if params[:page_id]
      @page = Page.find(params[:page_id])
    end
  end
end

Upvotes: 0

Views: 1255

Answers (2)

Richard Peck
Richard Peck

Reputation: 76774

Accept @VishalJAIN's answer, this is just an add-in for your second question.


Error

Each computer error is specific; 80% of the battle is identifying the error itself.

Your error is relatively common with Rails:

undefined method for ...

This means that you're calling a "method" which is not recognized by the interpreter:

@pages.collect {|p| [p.name, p.id]})

... @pages either doesn't have the collect method, or you @pages variable is not defined.

As pointed out in the comments, adding @pages = ... in your new action clears up the problem.

--

Cause

The cause of the error is that since Ruby, and by virtue Rails, is object orientated, every time you call a variable / method, Ruby needs to have it available.

In most languages, you'd receive a "variable undeclared" error -- variables can only be referenced if they're defined; Ruby puts everything into objects:

undefined method 'collect' for "nil:NilClass"

If you ever see the above error in your application, it means you haven't declared a variable that you're referencing.

Upvotes: 2

Vishal Jain
Vishal Jain

Reputation: 1940

Hey you have trying to call collect method on your @pages object on form which is nil

so replace your code in your new action as

def new
    @section = Section.new({:name => "Default", :page_id => @page.id})
    @section_count = Section.count +1
    @pages = @page.subject.pages.sorted
end

now @pages is not null so you can call collect method on it.

Upvotes: 2

Related Questions