1

这是我的代码:

// 在swimmer.rb(模型)中:

    belongs_to :user

// 在 user.rb (model) 中:

    has_one :swimmer, :dependent => :destroy
    accepts_nested_attributes_for :swimmer, :allow_destroy => true   
    attr_accessible :swimmer_attributes

// 在游泳者控制器.rb 中:

  def profile
    @swimmer = Swimmer.find_by_user_id(current_user)
    @swimmer_nickname = @swimmer.nickname
    @swimmer_gender = @swimmer.gender
    @title = "Swimmer Profile for #{@current_user.email}"
  end

// 在 profile.html.erb 中(在游泳者视图文件夹中)

   <% if @swimmer %>
     <h3><%= @title %></h3>
     <p>Nickname: <%= @swimmer_nickname %></p>
     <p>Gender: <%= @swimmer_gender %></p>
   <% else %>
     <h3>No Swimmer Profile for<%= current_user.email %></h3>
   <% end %>

如果游泳者对象的 user_id 与游泳者#controller 方法中的 @swimmer 实例变量匹配,因为有一个登录用户(使用 Devise gem)并且已经为该用户创建了一个游泳者,那么配置文件视图的工作方式为故意的。如果没有,页面会显示错误:

   NoMethodError (undefined method `nickname' for nil:NilClass):
     app/controllers/swimmers_controller.rb:66:in `profile'

但由于配置文件视图具有 if/else 条件,我希望缺少与登录用户关联的游泳者对象以强制视图显示 else 内容。显然,“Swimmer.find_by_user_id(current_user)”方法是在 NilClass 中创建一个 nil 对象。我如何得到它以使其不产生任何东西,从而产生 else 条件?

回购位于https://github.com/drollwit/vst2/tree/ver2。这是一个练习,而不是一个真正的项目。这里可能有一个简单的答案,但我想不通(仍在学习 Rails 基础知识)。任何帮助,将不胜感激。

4

2 回答 2

1

问题不在于视图,而在于您的配置文件方法:

def profile
  @swimmer = Swimmer.find_by_user_id(current_user)
  @swimmer_nickname = @swimmer.nickname
  @swimmer_gender = @swimmer.gender
  @title = "Swimmer Profile for #{@current_user.email}"
end

如果找不到游泳者,则 @swimmer 为 nil,并且以下行失败,因为您在 nil 上调用方法“昵称”。

一个简单的修复如下:

def profile
  @swimmer = Swimmer.find_by_user_id(current_user)
  @swimmer_nickname = @swimmer.try(:nickname)
  @swimmer_gender = @swimmer.try(:gender)
  @title = "Swimmer Profile for #{@current_user.email}"
end

现在,如果 @swimmer 不存在,@simmwer_nickname 和 @swimmer_gender 将被设置为 nil。请参阅http://api.rubyonrails.org/classes/NilClass.html#method-i-try

就个人而言,我不会像这样在控制器中分配这些额外的实例变量。我会将其移至视图或助手。

于 2012-04-18T05:44:28.377 回答
1

错误的原因存在于下面的代码行中。

@swimmer = Swimmer.find_by_user_id(current_user)

它永远不会根据 user_id 找到 Swimmer。因为

find_by_user_id

需要一个 ID。试试

@swimmer = Swimmer.find_by_user_id(current_user.id)

您将获得游泳者对象,然后将不会发生错误。

您可以通过以下方式改进查看文件

<% if @swimmer %>
 <h3><%= "Swimmer Profile for #{@current_user.email}" %></h3>
 <p>Nickname: <%= @swimmer.nickname %></p>
 <p>Gender: <%= @swimmer.gender %></p>
<% else %>
 <h3>No Swimmer Profile for<%= current_user.email %></h3>
<% end %>

这将减少来自控制器的以下代码行。

@swimmer_nickname = @swimmer.nickname
@swimmer_gender = @swimmer.gender
@title = "Swimmer Profile for #{@current_user.email}"
于 2012-04-18T07:16:20.640 回答