【问题标题】:undefined method `include?' for nil:NilClass with partial validation of wizard gem未定义的方法“包括?”对于 nil:NilClass 部分验证向导 gem
【发布时间】:2013-08-05 16:42:19
【问题描述】:

我正在尝试按照指南使用向导 gem 对对象进行部分验证,但我不断收到错误未定义方法“包括?”对于 nil:NilClass,无法理解哪里出了问题,已尝试按照分步说明进行操作。

日志中显示的错误。

NoMethodError - undefined method `include?' for nil:NilClass:
app/models/property.rb:22:in `active_or_tenants?'

这是我的步数控制器。

class Properties::BuildController < ApplicationController
  include Wicked::Wizard

  steps :tenant, :confirmed 

  def show
    @property = Property.find(params[:property_id])
    @tenants = @property.tenants.new(params[:tenant_id])
    render_wizard
  end

  def update
    @property = Property.find(params[:property_id])
    params[:property][:status] = step.to_s
    params[:property][:status] = 'active' if step == steps.last
    @property.update_attributes(params[:property])
    render_wizard @property
  end

  def create
    @property = current_user.properties.build(params[:property])
      logger.info @property.attributes
    if @property.save
        flash[:success] = "Tenant Added"
        redirect_to wizard_path(steps.second, :property_id => @property.id)
    else
        render 'edit'
    end
  end
end

属性.rb

class Property < ActiveRecord::Base
  attr_accessible  :name, :address_attributes, :tenants_attributes, :property_id, :status
  belongs_to :user 

  has_one :address, :as => :addressable
  accepts_nested_attributes_for :address, :allow_destroy => true

  has_many :tenants 
  accepts_nested_attributes_for :tenants, :allow_destroy => true

  validates :name,        :presence => true
  validates :address,     :presence => true
  validates :tenants,     :presence => true, :if => :active_or_tenants?

  def active?
    status == 'active'
  end

  def active_or_tenants?
    status.include?('tenants') || active?
  end
end

如果您需要在问题中添加任何其他部分,请告诉我。提前致谢。

【问题讨论】:

  • 错误来自哪一行?
  • property.rb NoMethodError 中的第 22 行 - 未定义的方法 include?' for nil:NilClass: app/models/property.rb:22:in active_or_tenants?'
  • 哦!我明白了......状态实际上是Property类的一个列(属性),对吧?如果是,则将status.include?('tenants') || active? 替换为(status || '').include?('tenants') || active?
  • 解决了,能解释一下两者的区别吗?
  • 是的,我要发布答案;)

标签: ruby-on-rails ruby-on-rails-3 validation formwizard


【解决方案1】:

来自我的cmets:

status 是您的 Property 模型的一个属性。它可以是nil,在某些情况下会引发错误:

undefined method include?' for nil:NilClass

它实际上是在尝试将nil'tenants'(字符串)进行比较。

要解决这个问题,如果statusnil,您可以使用空字符串进行比较,

# an example (you can try in your IRB console):
nil || "No value"
# => returns "No value"

在你的情况下:

def active_or_tenants?
  status.to_s.include?('tenants') || active?
end

nil.to_s 返回一个空字符串。这解决了你的问题;)


其实经常使用to_sto_ito_f等方法来去除可能的nil

# in ruby console:
2.3.3 :018 > nil.to_i
# => 0 
2.3.3 :019 > nil.to_f
# => 0.0 
2.3.3 :020 > nil.to_s
# => "" 
2.3.3 :021 > nil.to_a
# => [] 

【讨论】:

  • 我正在按照本指南 goo.gl/mKDxey 使用向导 gem 对对象进行部分验证,您认为这仍然会使部分验证工作吗?
  • 是的,因为它会返回相同的东西,本教程没有处理“status”列可能的 nil 值
【解决方案2】:

在 Ruby 2.3 中,您可以使用 safe navigation operator,当您的对象为 nil 时,它会简单地返回 nil,并且不会抛出错误。

def active_or_tenants?
  status&.include?('tenants') || active?
end

【讨论】:

  • 属性status不是数组而是字符串。
  • 谢谢MrYoshiji,我不知道我是怎么错过的,我会更新我的答案。
【解决方案3】:

对此还有另一种解决方案,您可能希望在对象创建时设置默认状态,这在迁移中更可取。

class AddStatusToProperties < ActiveRecord::Migration
  def change
    create_table :projects do |t|
      t.string :status, default: 'new'
    end
  end
end

按照此操作,您的州将永远不会有 nil

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-28
    • 1970-01-01
    • 2014-03-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多