web-dev-qa-db-ja.com

未定義のメソッド `include? 'ウィザードgemの部分的な検証を伴うnil:NilClassの場合

ウィザードgemを使用してオブジェクトの部分的な検証のガイドに従おうとしていますが、未定義のメソッド `include? 'というエラーが発生し続けます。 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

Property.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

質問に他の部分を追加する必要がある場合はお知らせください。前もって感謝します。

10
cyclopse87

私のコメントから:

statusは、プロパティモデルの属性です。 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
# => [] 
6
MrYoshiji

Ruby 2.3では、 安全なナビゲーション演算子 を使用できます。これは、オブジェクトがnilの場合に単にnilを返し、エラーをスローしません。

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

これには別の解決策があります。オブジェクトの作成時にデフォルトの状態を設定することをお勧めします。これは移行で望ましい方法です。

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

これに続いて、あなたはあなたの州のためにnilを持つことは決してないでしょう

1
Tomaž Zaman