簡體   English   中英

NoMethodError:nil:NilClass的未定義方法''

[英]NoMethodError: undefined method '' for nil:NilClass

我有以下模型和控制器代碼:

class Item < ActiveRecord::Base
 has_many :receivers_collateral_items, through: :received_trades, source: :wanted_item
 has_many :receivers_wanted_items, through: :received_trades, source: :collateral_item
 has_many :requesters_collateral_items, through: :requested_trades, source: :collateral_item
 has_many :requesters_wanted_items, through: :requested_trades, source: :wanted_item
 validates :year, :price, presence: true, numericality: true
 validates :shares, numericality: 
                     { only_integer: true, greater_than_or_equal_to: 0, 
                     less_than_or_equal_to: :build_shares }

 accepts_nested_attributes_for :receivers_collateral_items, :receivers_wanted_items, 
                               :requesters_collateral_items, :requesters_wanted_items, 
                               allow_destroy: true
end




class Trade < ActiveRecord::Base
 belongs_to :trade_requester, class_name: "User"
 belongs_to :trade_recipient, class_name: "User"
 belongs_to :wanted_item, class_name: "Item"
 belongs_to :collateral_item, class_name: "Item"
 validates :trade_requester, :trade_recipient, :wanted_item, :collateral_item, presence: true
 validates :shares, numericality: 
                     { only_integer: true, greater_than_or_equal_to: 0, 
                     less_than_or_equal_to: :max_shares }

 accepts_nested_attributes_for :wanted_item, :collateral_item, allow_destroy: true

 def max_shares
    if wanted_item.shares > collateral_item.shares
        collateral_item.shares
    else
        wanted_item.shares
    end
 end
end


class TradesController < ApplicationController
 def create
  @trade = current_user.requested_trades.build(trade_params)
 end

 private
  def trade_params
   params.require(:trade).permit(:trade_requester_id, :trade_recipient_id, :wanted_item_id, :collateral_item_id, :shares)
  end
end

但是我得到了NoMethodError: undefined method 'shares' for nil:NilClass和bd回滾的NoMethodError: undefined method 'shares' for nil:NilClass 重現錯誤的步驟:

t = Trade.new
t.trade_requester_id = User.find(1)
t.trade_recipient_id = User.find(2)
t.wanted_item_id = Item.second
t.collateral_item_id = Item.first
t.shares = 100
t.save

堆棧跟蹤表明它來自Tradenumericality驗證,但在我看來, 應該存在被調用的類shares 我應該能夠調用t.wanted_item並獲得該項目,但我得到nil t.wanted_item_id ,但是,返回該ID。 為什么是這樣?

這可能是因為新記錄確實缺少了wanted_itemcollateral_item 如果這兩個關聯中的nil一個返回nil ,則將引發異常。 要解決此問題,請try使用較舊版本的Ruby,或使用安全導航操作符( &. )進行Ruby 2.3或更高版本。

這應該可以解決您的問題(Ruby 2.3之前的版本):

def max_shares
  if wanted_item.try(:shares).to_i > collateral_item.try(:shares).to_i
    wanted_item.shares
  else
    collateral_item.try(:shares).to_i
  end
end

如果wanted_item.sharescollateral_item.shares不是niltry方法將返回它們的值。 如果其中之一為niltry將捕獲異常並返回nil to_inil轉換為零。

因此,如果存在collateral_itemcollateral_item.try(:shares).to_i將返回shares的價值,如果collateral_itemnil ,它將返回零。

如果使用Ruby 2.3或更高版本,則應將_item.try(:shares).to_i_item&.shares.to_i 后者看起來干凈,執行速度更快

更新資料

為了進行復制,請確保將記錄分配給關聯而不是其ID:

t = Trade.new
t.trade_requester = User.find(1)
t.trade_recipient = User.find(2)
t.wanted_item = Item.second
t.collateral_item = Item.first
t.shares = 100
t.save!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM