Ruby on rails 使用第一个\u或\u create时nilClass的未定义方法“+”

Ruby on rails 使用第一个\u或\u create时nilClass的未定义方法“+”,ruby-on-rails,ruby,Ruby On Rails,Ruby,我有一个函数在记录上使用first_或_create,并且我需要能够在它存在的情况下在它的一个属性上使用+ Blob.where(user_id: user.id, item_id: item.id).first_or_create do |s| s.amount += amount end 但是,如果记录不存在,我不能使用+。这是语法问题还是我使用的first\u或\u create?仅当创建了一个新对象但未找到该对象时才会调用该块。如果模型没有给定字段的默认值,它将尝试调用nil值上的

我有一个函数在记录上使用first_或_create,并且我需要能够在它存在的情况下在它的一个属性上使用+

Blob.where(user_id: user.id, item_id: item.id).first_or_create do |s|
  s.amount += amount
end

但是,如果记录不存在,我不能使用+。这是语法问题还是我使用的first\u或\u create?

仅当创建了一个新对象但未找到该对象时才会调用该块。如果模型没有给定字段的默认值,它将尝试调用nil值上的+。你可以这样做,也许有更好的方法:

blob = Blob.where(user_id: user.id, item_id: item.id).first_or_create
blob.amount += amount if blob.amount.present?
在这种情况下,仅当对象已经存在时才执行求和,根据您的描述,该对象似乎是您的目标。如果要在任何情况下应用金额总和,如果记录尚不存在,则可以将金额初始化为0:

blob = Blob.where(user_id: user.id, item_id: item.id).first_or_create do |b|
  b.amount = 0
end
blob.amount += amount

在上面的示例中,如果存在一个对象,那么它将向当前值添加数量,否则它将使用0初始化属性,然后向其添加数量。

仅当创建了一个新对象但未找到该对象时才会调用该块。如果模型没有给定字段的默认值,它将尝试调用nil值上的+。你可以这样做,也许有更好的方法:

blob = Blob.where(user_id: user.id, item_id: item.id).first_or_create
blob.amount += amount if blob.amount.present?
在这种情况下,仅当对象已经存在时才执行求和,根据您的描述,该对象似乎是您的目标。如果要在任何情况下应用金额总和,如果记录尚不存在,则可以将金额初始化为0:

blob = Blob.where(user_id: user.id, item_id: item.id).first_or_create do |b|
  b.amount = 0
end
blob.amount += amount

在上面的示例中,如果存在对象,则该对象将向当前值添加金额,否则将使用0初始化属性,然后向其添加金额。

对s.amount执行空检查。如果之前不存在,则s.amount将为零,这自然无法添加到

您可以使用以下命令来完成此操作

Blob.where(user_id: user.id, item_id: item.id).first_or_create do |s|
  if s.amount.nil?
    s.amount = amount
  else
    s.amount += amount
  end
end

或者,您可以在字段上设置默认值0,尽管我对该值不是肯定的。

对s.amount执行空检查。如果之前不存在,则s.amount将为零,这自然无法添加到

您可以使用以下命令来完成此操作

Blob.where(user_id: user.id, item_id: item.id).first_or_create do |s|
  if s.amount.nil?
    s.amount = amount
  else
    s.amount += amount
  end
end

或者,您也可以在字段中设置默认值0,尽管我对此不肯定。

我不是投票反对者,我同意他们应该给出理由。但我认为原因可能是只有在创建新记录时才会调用块,而不是在发现新记录时才调用块。我不是投反对票的人,我同意他们应该给出一个理由。但我认为原因可能是只有在创建新记录时才调用块,而不是在找到新记录时才调用块。是否有任何原因表明s.amount具有nil值是有效的?我倾向于使用0作为默认金额更好,当然,数据库中的金额不为null。在db中将金额默认设置为0或不为null是否可以避免此问题?我会同时使用两种方法,即t.integer:amount、default:0、null:false。很遗憾,null:true是默认值,这很少是您想要的,并且会导致很多问题。是否有任何理由认为s.amount具有nil值是有效的?我倾向于使用0作为默认金额更好,当然,数据库中的金额不为null。在db中将金额默认设置为0或不为null是否可以避免此问题?我会同时使用两种方法,即t.integer:amount、default:0、null:false。很遗憾,null:true是默认值,这在我看来很少是你想要的,这会导致很多问题。好吧,等等,我还是很困惑。我想要的是记录如果存在就更新,如果不存在就创建。我不知道我什么时候接受了这个答案,但这只会在没有找到的情况下创建一个新对象。这是它的一半-另一半是更新记录,如果它被发现。嗯,这是愚蠢的。我原以为first_或_create应该做我期望的事情,但结果证明我需要编写自己的upsert功能或使用gem?是的,您需要在之后进行更新,first_或_create不处理upsert。某些数据库不支持upsert,而activerecord尝试使用泛型。如果您使用的是Postgres,它支持,那么您可以使用类似于gem的activerecord导入,它能够处理冲突时的upsert更新。您的后一个解决方案仍然有效。如果记录不存在,它将创建该记录,然后添加金额。这是一个额外的数据库查询,但我想现在还可以。非常感谢!好吧,等等,我还是很困惑。我想要的是记录如果存在就更新,如果不存在就创建。我不知道我什么时候接受了这个答案,但这只会在没有找到的情况下创建一个新对象。这是它的一半-另一半是更新记录,如果它被发现。嗯,这是愚蠢的。我原以为first_或_create应该做我期望的事情,但结果证明我需要编写自己的upsert功能或使用gem?是的,您需要在之后进行更新,first_或_create不处理upsert。某些数据库不支持upsert和activerecord
尽量泛化。如果您使用的是Postgres,它支持,那么您可以使用类似于gem的activerecord导入,它能够处理冲突时的upsert更新。您的后一个解决方案仍然有效。如果记录不存在,它将创建该记录,然后添加金额。这是一个额外的数据库查询,但我想现在还可以。非常感谢!