存在验证导致“未定义的方法`map'为nil:NilClass”错误

时间:2014-10-13 17:21:24

标签: ruby-on-rails ruby validation ruby-on-rails-4

我希望人们在写一个聚光灯之前定义一个课程名称。我通过将以下代码添加到聚光灯模型

来完成此操作
class Spotlight < ActiveRecord::Base
  validates :name, presence: true
end

在添加验证之前,我可以编写没有任何名称的聚光灯。如果我现在尝试,我会收到以下错误消息:

undefined method `map' for nil:NilClass
Extracted source (around line #29):

     </div>
     <div class="field">
       <%= f.label :name, "Opleiding" %><br>
       <%= f.collection_select(:name,  @colli,  :name, :name, {prompt: 'Selecteer een opleiding'}, {id: 'collis_select'}) %>
     </div>
     <div class="field">
       <%= f.label :teaser %><br>

这里发生了什么?集合选择是我填写其他字段的ajax调用的基础。

查看

<%= form_for(@spotlight) do |f| %>
  <% if @spotlight.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@spotlight.errors.count, "error") %> prohibited this spotlight from being saved:</h2>

      <ul>
      <% @spotlight.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :spotlight, "In de kijker" %><br>
    <%= f.check_box :spotlight %>
  </div>
  <div class="field">
    <%= f.label :start, "Start in de kijker" %><br>
    <%= f.datetime_select :start %>
  </div>
  <div class="field">
ruby-on-rails
    <%= f.label :stop, "Stop in de kijker" %><br>
    <%= f.datetime_select :stop %>
  </div>
  <div class="field">
    <%= f.label :name, "Opleiding" %><br>
    <%= f.collection_select(:name,  @colli,  :name, :name, {prompt: 'Selecteer een opleiding'}, {id: 'collis_select'}) %>
  </div>
  <div class="field">
    <%= f.label :teaser %><br>
    <%= f.text_area :teaser, size: "85x10", id: 'teasers_select' %>
  </div>
  <div class="field">
    <%= f.label :coursedate, "Startdatum opleiding" %><br>
    <%= f.datetime_select :coursedate, id: 'startdate_select' %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

<script>
  $(document).ready(function() {
    $('#collis_select').change(function() {
      $.ajax({
        url: "<%= update_teasers_path %>",
        data: {
          name : $('#collis_select').val()
        },
        dataType: "script"
      });
    });
  });
</script>

更新预告片视图

$('#teasers_select').val("<%= escape_javascript(@teaser) %>");

控制器

class SpotlightsController < ApplicationController
  before_action :set_spotlight, only: [:show, :edit, :update, :destroy]
  before_action :load_colli, only: [:new, :edit]

  def index
    @spotlights = Spotlight.all.order('spotlight DESC, start, stop')
  end

  def show
  end

  def new
    @spotlight = Spotlight.new
  end

  def edit
  end

  def create
    @spotlight = Spotlight.new(spotlight_params)

    respond_to do |format|
      if @spotlight.save
        format.html { redirect_to @spotlight, notice: 'Spotlight was successfully created.' }
        format.json { render action: 'show', status: :created, location: @spotlight }
      else
        format.html { render action: 'new' }
        format.json { render json: @spotlight.errors, status: :unprocessable_entity }
      end
    end
  end

  def update
    respond_to do |format|
      if @spotlight.update(spotlight_params)
        format.html { redirect_to @spotlight, notice: 'Spotlight was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: 'edit' }
        format.json { render json: @spotlight.errors, status: :unprocessable_entity }
      end
    end
  end

  def update_teasers
    # updates artists and songs based on genre selected
    colli = Colli.where(name: params[:name])

    # map to name and id for use in our options_for_select
    @teaser = colli.first.teaser
  end

  def destroy
    @spotlight.destroy
    respond_to do |format|
      format.html { redirect_to spotlights_url }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_spotlight
      @spotlight = Spotlight.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def spotlight_params
      params.require(:spotlight).permit(:spotlight, :start, :stop, :name, :teaser, :coursedate)
    end

    def load_colli
      @colli = Colli.select(:name).distinct.order('name')
    end

end

有人可以解释一下这似乎是什么问题吗?错误所指的“地图”功能是什么?

2 个答案:

答案 0 :(得分:0)

看起来你的@colli对象是零。

<%= f.collection_select(:name,  @colli,  :name, :name, {prompt: 'Selecteer een opleiding'}, {id: 'collis_select'}) %>

这与在线验证无关。确保collection_select方法正在接收@colli实例变量。现在它收到了零。

map function是类Array中的实例方法。它接收一个块,遍历一个数组,并返回一个新的数组,其中包含从块返回的元素。您无法在零上致电map;你会得到上面看到的错误。

您可以通过提升来检查@colli是否为nil

def load_colli
  @colli = Colli.select(:name).distinct.order('name')
  raise @colli.to_s
end

答案 1 :(得分:0)

如果将update_teasers函数更改为:

def update_teasers
 # updates artists and songs based on genre selected
 @colli = Colli.where(name: params[:name])

 # map to name and id for use in our options_for_select
 @teaser = @colli.first.teaser
end

应该解决问题。这不是存在验证的问题。

编辑:抱歉,这不起作用。接下来我将尝试在create函数中设置@colli变量,如下所示。这样,当变量在失败的保存时呈现新动作时,它仍然被设置。

def create
 @spotlight = Spotlight.new(spotlight_params)
 @colli = Colli.where(name: params[:name])


 respond_to do |format|
  if @spotlight.save
    format.html { redirect_to @spotlight, notice: 'Spotlight was successfully created.' }
    format.json { render action: 'show', status: :created, location: @spotlight }
  else
    format.html { render action: 'new' }
    format.json { render json: @spotlight.errors, status: :unprocessable_entity }
  end
 end
end