方法本身按预期工作,但当我尝试在模型规范中测试时,创建部分失败。查找部分运行良好。我错过了什么?
conversation.rb
scope :between, -> (sender_id, recipient_id) do
where("(conversations.sender_id = ? AND conversations.recipient_id = ?) OR (conversations.sender_id = ? AND conversations.recipient_id = ?)", sender_id, recipient_id, recipient_id, sender_id)
end
def self.create_or_find_conversation(task_assigner_id, task_executor_id)
Conversation.between(task_assigner_id, task_executor_id).first_or_create do |conversation|
conversation.sender_id = task_assigner_id
conversation.recipient_id = task_executor_id
end
end
conversation_spec.rb
describe "class methods" do
let(:sender) { create(:user) }
let(:recipient) { create(:user) }
let(:other_recipient) { create(:user) }
let!(:conversation) { create(:conversation, sender: sender, recipient: recipient) }
context "create_of_find_conversation" do
#this one throws Failure/Error: expect{conv}.to change{Conversation.count}.by(1)
#expected result to have changed by 1, but was changed by 0
it "creates conversation" do
conv = Conversation.create_or_find_conversation(sender, other_recipient)
expect{conv}.to change{Conversation.count}.by(1)
end
#this one is working as expected
it "finds conversation" do
conv = Conversation.create_or_find_conversation(sender, recipient)
expect(conv).to eq(conversation)
end
end
end
答案 0 :(得分:3)
我认为这些代码:
it "creates conversation" do
conv = Conversation.create_or_find_conversation(sender, other_recipient)
expect{conv}.to change{Conversation.count}.by(1)
end
应更改为:
it "creates conversation" do
expect{
Conversation.create_or_find_conversation(sender.id, other_recipient.id)
}.to change{Conversation.count}.by(1)
end
因为价值不是改变了计数,而是改变了过程。
答案 1 :(得分:0)
Ruby中的常规变量不是延迟加载 - 在赋值变量时会处理赋值的右侧。
def do_something(val)
puts "do_something called"
val
end
a = do_something(hello_world)
puts a
# do_something called
# hello world
您需要更改期望,以便在传递给期望的块内调用该操作:
it "creates conversation" do
expect do
Conversation.create_or_find_conversation(sender, other_recipient)
end.to change{Conversation.count}.by(1)
end
或者使用RSpec的let
创建一个延迟加载变量:
let(:conv) { Conversation.create_or_find_conversation(sender, other_recipient) }
it "creates conversation" do
expect { conv }.to change{Conversation.count}.by(1)
end
但这并不能解决您对域建模错误的根本问题。在对话中,双方轮流说话 - 因此使用recipient_id
和sender_id
是完全错误的。而是具有发送者和接收者的消息。
您可以将它们更改为您想要的任何内容,但使用适当的多对多关系会更加简单,这样您就不需要复杂的AND OR
查询。
class User < ActiveRecord::Base
has_many :user_conversations
has_many :conversations, through: user_conversations
end
class Conversation < ActiveRecord::Base
has_many :user_conversations
has_many :users, through: user_conversations
end
# the m2m join model.
class UserCoversation < ActiveRecord::Base
belongs_to :user
belongs_to :conversation
end
然后您可以简单地查询:
Conversation.where(users: [a, b])