不一致的rails方法`exists`和`any?`

时间:2018-02-12 21:57:46

标签: ruby-on-rails ruby ruby-on-rails-4

我正在开发基于Ruby on Rails的聊天。所以我最初在两个客户互相添加为朋友时创建一个对话,我Conversation的模型如下:

class Conversation < ActiveRecord::Base
  has_many :messages
  belongs_to :player_client
  belongs_to :client
end

现在当player_client点击特定按钮时,我想为他们创建一个自动消息。只有当他们从未向对方发送过消息,即对话没有相关消息时,才会发生这种情况。

从控制台尝试以下方法:

@conversation = Conversation.find(7)
@conversation.messages.any?
> False
@conversation.messages.empty?
> True
@conversation.messages.exists?
> False

所有预期值均为。但是在我的Rails代码中添加任何这些方法都会引发错误:

NoMethodError (undefined method `messages' for #<Conversation::ActiveRecord_AssociationRelation:0x007fa187ca1ec8>)`

我猜这是因为该对话不存在消息,因此无法找到该对话的任何关联。我不确定为什么这种方法会不一致。

编辑:添加导致错误的代码。

conversation_with_player_client = @ client.conversations.select {| c | c.player_client_id == @ game.player_client.id}

if conversation_with_player_client.count == 0
  @conversation = @client.conversations.build({player_client_id: @game.player_client.id})
  @conversation.save!
else
  @conversation = @client.conversations.where({ player_client_id: @game.player_client.id })
end

puts "the conversation we found was #{@conversation.inspect}"
# This gives the response
# #<Conversation id: 7, player_client_id: 1, client_id: 11, created_at: "2018-02-12 20:55:55", updated_at: "2018-02-12 20:55:55">
# in the console so it can get the conversation 

if @conversation.messages.any?

# this line is causing the error

4 个答案:

答案 0 :(得分:2)

该错误是由于您在对话的集合上调用messages而非单个对话。

我愿意打赌违规代码是这样的:

client.conversations.messages #=> NoMethodError

相反,它应该是:

client.conversations.first.messages

编辑 - 这是导致错误的行:

@conversation = @client.conversations.where({ player_client: @game.player_client.id })

where将返回表示多个会话的关系。如果您只想进行一次对话,可以使用find_by

@conversation = @client.conversations.find_by({ player_client: @game.player_client.id })

答案 1 :(得分:0)

您是否尝试使用present?方法?猜猜它会更好......就像这样:

@conversation.messages.present?

如果消息为零或空,它将返回false,所以我猜它更适合。祝你好运!

答案 2 :(得分:0)

在您的代码中:

@conversation = @client.conversations.where({ player_client: @game.player_client.id })

不是对话。不止一个。你不能在那里使用消息。

如果您只需要一次会话,则必须通过find_by更改位置。

如果没有,您需要遍历所有对话。

答案 3 :(得分:0)

find_or_create_by方法的另一种方式:

@client.conversations.find_or_create_by(player_client: @game.player_client.id)

要查找更多信息:

https://apidock.com/rails/v4.0.2/ActiveRecord/Relation/find_or_create_by