1

我正在尝试为学生创建一个注册,以便能够注册他们可用的部分。但是,当我实际点击创建注册按钮时,我不断收到此错误。当我检查实时外壳时,它说@student == nil 意味着它没有被正确创建?我对如何解决这个问题感到困惑

<!---REGISTRATION CONTROLLER-->

def new
    @registration = Registration.new
    @student = Student.find(params[:student_id])
    @info = Section.for_rank(@student.rank).for_age(@student.age).map{|s| ["Name: #{Event.find_by_id(s.event.id).name}, 
        Ranks: #{ s.max_rank == nil ? "#{Student::RANKS[s.min_rank-1][0]} and up" : "#{Student::RANKS[s.min_rank-1][0]} - #{Student::RANKS[s.max_rank-1][0]}"},
        Ages: #{ s.max_age == nil ? "#{s.min_age} and up" : "#{s.min_age} - #{s.max_age}" }", s.id] }
end


def create
    @registration = Registration.new(params[:registration])
    if @registration.save
        redirect_to @registration, :notice => "Successful"
    else
        render :action => 'new'
    end
end

<!----MY REGISTRATION FORM -->

<div class="field">
<%= f.hidden_field :student_id, :value => @registration.student_id %>

<div class = "field">
<%= f.select :section_id, options_for_select(@info)%>

<div class="actions">
<%= f.submit nil, :class => 'btn btn-mini'  %></th>

<!--- MY STUDENT SHOW THAT CALLS THE REGISTRATION -->

<%= link_to 'Register ', new_registration_path(:student_id => @student.id), :class => 'btn btn-mini'  %>
4

1 回答 1

0

I don't know what the answer to your particular question is, but there is a problem with this method - it's defining presentation in the controller, which is not the controller's responsibility.

Whatever you're trying to do in the map block, it's a huge mess. If something goes wrong in there, and I can all but guarantee that it eventually will, it will be unnecessarily difficult to debug. It looks complicated enough that you should probably make a few presenter classes to handle the select options generation, so all you would need to do is something like this:

SectionSelectOptions.new(@student).to_options

The SectionSelectOptions class might be something like this:

class SectionSelectOptions
  attr_reader :student

  def initialize(student)
    raise ArgumentError unless student
    @student = student
  end

  def to_options
    sections.map {|section| SectionOption.new(section, student).to_option }
  end

  private

  def sections
    Section.for_rank(student.rank).for_age(student.age)
  end

end

And the SectionOption class:

class SectionOption
  attr_reader :section, :student
  def initialize(section, student)
    @section = section
    @student = student
  end

  def to_option
    ["#{name}, #{ranks}, #{ages}", section.id]
  end

  private

  def name
    "Name: #{section.event.name}"
  end

  def ranks
    "..." # I'll let you refactor whatever is going on here
  end

  def ages
    "..."
  end
end

Granted, it's longer than the single line of code that's creating the issue for you, but this has several advantages:

  1. It splits every step into it's own method, so when you're interface changes, you have one place to change it (e.g., it the lookup for sections changes, you just change the sections method)

  2. It's testable, either through the public interface or through individual methods

  3. It's easier to debug. You'll now know exactly what's going on when something goes wrong, because your errors will tell you which method to look at.

于 2013-03-31T21:58:38.383 回答