这不应该是零

时间:2014-04-26 23:42:54

标签: ruby-on-rails rspec entity-relationship relationship models

我有一个简单的测试:

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
嗯......

怎么回事?

  • 一个:用户的我的博客关联没有ID。
  • 两个:@ user.blogs,返回该用户的所有博客,但@ user.blogs.find_by(title:@ blog.title)返回nil? oO

怎么回事?

有趣的额外信息

模型

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

2 个答案:

答案 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。使用其中之一,您的测试将以更加可预测的方式运行。