如何使用Factory Girl/Bot定义多态关联

13

我有一个用户和故事模型,它们都有评论。

我声明了如下的模型:

class Comment
  belongs_to :commentable, polymorphic: true
  belongs_to :user
end

class User
end

class Story
end

现在,我想使用 FactoryGirl 声明一个评论对象,该对象属于与 commendable 和 user 相同的用户。

以下是迄今为止的代码:

FactoryGirl.define do
  factory :user do
    sequence(:email) {|n| "person#{n}@exmaple.com"}
    sequence(:slug) {|n| "person#{n}"}
  end

  factory :comment do    
    occured_at { 5.hours.ago }
    user
    association :commentable, factory: :user
  end

end

问题在于编写评论的用户和可评论的用户不同。

我为什么要解决这个问题?

非常感谢。


您也可以在此处找到此问题的解决方案:https://dev59.com/VWsz5IYBdhLWcg3wpZry#24228599 - Kingsley Ijomah
我看到所有的回复都建议使用2个工厂或带有特征的工厂 - 似乎我们不能使用多态关联来创建工厂(尽管这是有道理的)。 - LE-HU
2个回答

15

首先,我认为您还没有完成设置关联... 我想这就是您想要的:

class Comment < AR
  belongs_to :commentable, polymorphic: true
end

class User < AR
  has_many :comments, as: :commentable
end

class Story < AR
  has_many :comments, as: :commentable
end
请见:http://guides.rubyonrails.org/association_basics.html#polymorphic-associations 不要忘记进行数据库设置。
其次,Factory设置返回两个用户是因为你告诉它这样做了。尝试使用以下代码:
FactoryGirl.define do
  factory :user do
    sequence(:email) {|n| "person#{n}@exmaple.com"}
    sequence(:slug) {|n| "person#{n}"}
  end

  factory :comment do    
    occured_at { 5.hours.ago }
    association :commentable, factory: :user
  end

end

从风格上看,模型名称的选择有些令人困惑。用户如何“可评论”?如果你的意思是其他类型的写作,我会选择另一个名称。同样的,如果您的意思是“用户资料”或类似的东西,也应该选择不同的名称。


好的,但问题是,我如何将一个用户对象关联到两个“属于”关联?我想将可评论的同一用户添加到评论类中的用户属性。 - gilsilas

7

我看到了这个问题因为我个人有一个类似的问题并解决了它。像@jordanpg一样,我很好奇一个用户如何可评论。如果我理解正确,问题是写故事的用户和评论故事的用户可能是不同的用户:

  • user_1 写了一个故事
  • user_2(或任何用户)可以评论 user_1 的故事

为了做到这一点,我会设置以下模型关联:

# app/models/user.rb
class User < ApplicationRecord
  has_many :stories
  has_many :comments
end

# app/models/story.rb
class Story < ApplicationRecord
  belongs_to :user
  has_many :comments, as: :commentable
end

# app/models/comment.rb
class Comment < ApplicationRecord
  belongs_to :user
  belongs_to :commentable, polymorphic: true
end

在我的工厂里,它会是这样的:
# spec/factories.rb
FactoryBot.define do

  factory :user do
    sequence(:email) {|n| "person#{n}@example.com"}
    sequence(:slug) {|n| "person#{n}"}
  end

  factory :story do
    body "this is the story body"
    user
  end

  factory :comment do
    body "this is a comment on a story"
    user
    association :commentable, factory: :story
  end
end

这个做法的一部分原因在于factory_bot会自动构建您正在创建的任何子对象的父对象。他们关于关联的文档相当不错:http://www.rubydoc.info/gems/factory_bot/file/GETTING_STARTED.md#Associations 如果您需要让用户能够对评论进行评论,则可以这样做:
  factory :comment_on_story, class: Comment do
    body "this is a comment on a story"
    user
    association :commentable, factory: :story
  end

  factory :comment_on_comment, class: Comment do
    body "this is a comment on a comment"
    user
    association :commentable, factory: :comment_on_story
  end

我认为你的 factory :post 应该改成 factory :story - Ritchie
:facepalm: 你说得完全正确 @Ritchie 。感谢你指出来!我已经修复了。 - richardsonae

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接