1

我一直在关注 Michael Hartl 的 Rails 教程。实际上我已经完成了它,但是我在为最后一章的最后一个练习所做的一些重构时遇到了一些问题。我所做的只是改变用户模型(show.html.erb)的显示视图:

<section>
  <h1>
    <%= gravatar_for @user %>
    <%= @user.name %>
  </h1>
</section>

对此:

<section>      
   <%= render 'shared/user_info' %>
</section>

在部分(_user_info.html.erb)我有这个:

<a href="<%= user_path(current_user) %>">
   <%= gravatar_for current_user, size: 52 %> 
</a> 
<h1> <%= current_user.name %> </h1> 
<% unless current_page?(user_path(current_user)) %> 
   <span> <%= link_to "view my profile", current_user %> </span>
   <span> <%= pluralize(current_user.microposts.count, "micropost") %> </span>
<% end %>

在浏览器上一切正常,但由于某种原因 rspec 未能通过某些测试,我怀疑 rspec 在调用 session_helper.rb 中定义的 current_user 方法时遇到问题,顺便说一下,该方法包含在 application_helper.rb 中。gravatar_for 函数在 users_helper.rb 中定义。这是我从测试中得到的错误:

失败/错误:在 { 访问 user_path(user) } ActionView::Template::Error: 未定义方法email' for nil:NilClass # ./app/helpers/users_helper.rb:4:ingravatar_for'_app_views_shared__user_info_html_erb___3480157814439046731_47327400' # ./app/views/users/show.html.erb:5:in之前/user_pages_spec.rb:58:in `block (3 levels) in '

如果您能帮助我确定这里发生了什么,我将不胜感激。我可以找到不同的方法来做同样的事情,但我对此非常好奇。我在 Rails 方面不是很有经验,这就是为什么我遵循本教程的原因,如果我遗漏了一些明显的东西,请原谅我。谢谢。

4

3 回答 3

3

我想我得到了解决方案。虽然我还是一头雾水。这是我的问题中提到的重构之前的测试代码(因为它们在教程中,它们都通过了):

describe "profile page" do
  let(:user) { FactoryGirl.create(:user) }
  let!(:m1) { FactoryGirl.create(:micropost, user: user, content: "Foo") }
  let!(:m2) { FactoryGirl.create(:micropost, user: user, content: "Bar") }

  before { visit user_path(user) }

  it { should have_selector('h1',    text: user.name) }
  it { should have_selector('title', text: user.name) }

  describe "microposts" do
    it { should have_content(m1.content) }
    it { should have_content(m2.content) }
    it { should have_content(user.microposts.count) }
  end #some other tests for show page continue, also having the same behaviour
end

在阅读测试以查看是否有错误时,我开始想知道如果我没有让用户登录,为什么这些测试会通过,所以我在 before 块中添加了代码来让用户登录,如下所示:

describe "profile page" do
  let(:user) { FactoryGirl.create(:user) }
  let!(:m1) { FactoryGirl.create(:micropost, user: user, content: "Foo") }
  let!(:m2) { FactoryGirl.create(:micropost, user: user, content: "Bar") }

  before do
    valid_signin user
    visit user_path(user) 
  end

  it { should have_selector('h1',    text: user.name) }
  it { should have_selector('title', text: user.name) }

  describe "microposts" do
    it { should have_content(m1.content) }
    it { should have_content(m2.content) }
    it { should have_content(user.microposts.count) }
  end #some other tests for show page continue, also having the same behaviour
end

现在所有测试都通过了。我知道登录用户似乎很愚蠢而且很明显,但是这就是教程中的测试方式,并且它们之前一直在工作。如果您想检查它,这是更新的测试文件。所有更改现在都提交到我的 github 存储库中。谢谢大家的帮助。

于 2012-07-12T03:26:00.637 回答
2

查看您的 repo,这可能是问题所在:Rails 教程于 6 月 25 日报告了一个关于app/helpers/sessions_helper.rb文件current_user中的sign_insign_out方法的设置的小错误。该通知似乎没有发布在Rails 教程新闻网站上,但已发送给订阅者,并且反映在当前在线书籍中说要更改:

self.current_user = user   # in the sign_in method
self.current_user = nil    # in the sign_out method

因此,请尝试更新您的sessions_helper.rb,看看是否会阻止您获得nil用户。

于 2012-07-11T15:35:20.713 回答
1

听起来您的测试数据库中没有任何用户。开发数据库和测试数据库是两个不同的东西。Rspec 在运行测试时使用测试数据库。

要设置您所做的测试数据库rake db:test:prepare

然后,您需要在运行规范时填充测试数据库。一种很好的方法是使用Factory Girl宝石。

于 2012-07-11T11:26:59.553 回答