我有一个简单的测试:
it "should create a post through a user for a blog." do
@user.blogs.create(title: @blog.title)
@user.blogs.find_by_title(@blog.title).posts.create(title: 'some title')
post = Post.find_by_title('some title')
post.title.should == 'some title'
end
这失败了。为什么?因为我们没有为用户提供任何博客。好吧,让我们在他们的:{/ p>中抛出一个binding.pry
it "should create a post through a user for a blog." do
@user.blogs.create(title: @blog.title)
binding.pry
@user.blogs.find_by_title(@blog.title).posts.create(title: 'some title')
post = Post.find_by_title('some title')
post.title.should == 'some title'
end
现在在控制台中,让我们看看@user.blogs
是否给了我们任何东西。
@user.blogs
=> [#<Blog id: nil, title: "user_blog_26">]
好的....但那不是整个命令。让我们看看@blogs是否有任何内容。
@blog
=> #<Blog id: 26, title: "user_blog_26">
好的,我们在某些地方,我们看到@user
有与之关联的博客。 (虽然@user.blogs
中缺少ID ...(注意:用户与博客之间的关系为:User has_and_belongs_to_many :blogs, join_table: 'blogs_users'
)
所以我们这样做:
@user.blogs.find_by(title: @blog.title)
=> nil
嗯......
怎么回事?
怎么回事?
模型
class User < ActiveRecord::Base
include Promiscuous::Subscriber
subscribe :first_name, :email, :user_name, :last_name
has_and_belongs_to_many :blogs, join_table: 'blogs_users'
has_many :posts, through: :blogs
validates :first_name, presence: true
validates :email, presence: true, uniqueness: true
validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
end
class Blog < ActiveRecord::Base
has_many :posts
validates :title, presence: true, uniqueness: true
end
答案 0 :(得分:1)
@blog
=> #<Blog id: 26, title: "user_blog_26">
@blog
已分配id
。因此,这意味着它是blogs
表中id = 26
的现有记录。
@user.blogs.create(title: @blog.title)
此行表示在博客表格中创建一个新记录,其标题与@blog.title
的标题相同(即user_blog_26
)
现在,在Blog
模型中你有
validates :title, presence: true, uniqueness: true ## title must be unique
title
字段的唯一性检查。因此,显然@user.blogs.create(title: @blog.title)
失败,因为user_blog_26
表中已存在标题为blogs
的记录(此处为Recall @blog)。这就是@user.blogs
显示id = nil
博客时associated blog
创建失败的原因。
@user.blogs.find_by(title: @blog.title)
=> nil
由于未为associated blog
创建标题为user_blog_26
的{{1}}。此查询返回@user
。
可能的解决方案
nil
引用的数据库中已有blog
条记录。要将该博客分配到@blog
,只需更新以下示例:
@user
答案 1 :(得分:0)
在测试代码时,您应该将测试隔离形成世界 - 它们不应该通过或失败,因为您的真实数据库缺少行,或者存在意外行。
出于这个原因,您应该使用某种方法,在每次测试开始时,您设置数据库以包含仅测试所需的内容,以及在测试结束时,您应该拆除数据库,为下一次测试做好准备。
有一些宝石可以帮助您实现这一策略,例如database cleaner。使用其中之一,您的测试将以更加可预测的方式运行。