неопределенный метод `включить?' для nil:NilClass с частичной проверкой драгоценного камня мастера

Я пытаюсь следовать руководству по частичной проверке объекта с помощью драгоценного камня мастера, но я продолжаю получать сообщение об ошибке неопределенного метода `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

Недвижимость.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

Дайте мне знать, если вам нужны какие-либо другие части, добавленные к вопросу. Заранее спасибо.


person cyclopse87    schedule 05.08.2013    source источник
comment
Из какой строки исходит ошибка?   -  person MrYoshiji    schedule 05.08.2013
comment
строка 22 в файле property.rb NoMethodError — неопределенный метод include?' for nil:NilClass: app/models/property.rb:22:in active_or_tenants?'   -  person cyclopse87    schedule 05.08.2013
comment
Ой! Ясно... Статус на самом деле является столбцом (атрибутом) класса Property, верно? Если да, то замените status.include?('tenants') || active? на (status || '').include?('tenants') || active?   -  person MrYoshiji    schedule 05.08.2013
comment
Это исправлено, не могли бы вы объяснить разницу между ними, пожалуйста?   -  person cyclopse87    schedule 05.08.2013
comment
Да, я напишу ответ ;)   -  person MrYoshiji    schedule 05.08.2013


Ответы (3)


Из моих комментариев:

status — это атрибут вашей модели собственности. Это может быть nil, что в некоторых случаях вызывает ошибку:

undefined method include?' for nil:NilClass

На самом деле он пытается сравнить nil с 'tenants' (String).

Чтобы исправить это, вы можете использовать пустую строку для сравнения, если status равно nil,

# 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_s, to_i, to_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
# => [] 
person MrYoshiji    schedule 05.08.2013
comment
Я следую этому руководству goo.gl/mKDxey для частичной проверки объектов с помощью драгоценного камня мастера, как вы думаете, это все еще заставит частичную проверку работать? - person cyclopse87; 05.08.2013
comment
Да, потому что он вернет одно и то же. Учебник не обрабатывает возможное нулевое значение для статуса столбца. - person MrYoshiji; 05.08.2013

В Ruby 2.3 вы можете использовать оператор безопасной навигации, который просто возвращает nil, когда вы объект равен нулю, и он не выдаст ошибку.

def active_or_tenants?
  status&.include?('tenants') || active?
end
person Omar Bahareth    schedule 16.01.2017
comment
атрибут status — это не массив, а строка. - person MrYoshiji; 17.01.2017
comment
Спасибо MrYoshiji, я не знаю, как я это пропустил, я обновлю свой ответ. - person Omar Bahareth; 18.01.2017

Есть еще одно решение: вы можете установить состояние по умолчанию при создании объекта, что предпочтительнее при миграции.

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

После этого у вас никогда не будет nil для вашего штата

person Tomaž Zaman    schedule 19.10.2013