to_param不能在嵌套的多态关联模型中工作

时间:2015-01-16 18:04:20

标签: ruby-on-rails

此测试在get_users_path

失败
require 'test_helper'
class UsersIndexTest < ActionDispatch::IntegrationTest
  def setup
    @admin = users(:user_baz)
  end

  test "index as admin including pagination and delete links" do
    log_in_as(@admin)
    get users_path
    .
    .
  end
end

以下是错误消息:

ActionView::Template::Error: undefined method 'callsign' for nil:NilClass
        app/models/user.rb:35:in 'to_param'
        app/views/users/_user.html.erb:3:in '_app_views_users__user_html_erb___623096829469928541_2227766840'
        app/views/users/index.html.erb:8:in '_app_views_users_index_html_erb__62429272046032246_2224894860'
        test/integration/users_index_test.rb:9:in `block in <class:UsersIndexTest>'`

它指的是用户模型中self.character.callsign方法中的行to_param

User.rb:

class User < ActiveRecord::Base
  attr_accessor :remember_token, :activation_token, :reset_token
  has_one  :character, as: :sociable, dependent: :destroy
  accepts_nested_attributes_for :character
  has_secure_password
  before_validation do
    self.create_character unless character
  end
  before_save do
    self.email.downcase!
  end
  before_create :create_activation_digest
  validates :name, presence: true,
                   length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(?:\.[a-z\d\-]+)*\.[a-z]+\z/i
  validates :email, presence:   true,
                    format:     { with: VALID_EMAIL_REGEX },
                    uniqueness: { case_sensitive: false }
  validates :password, length: { minimum: 6 }, allow_blank: true
  validates :character, presence: true

  def to_param
    self.character.callsign
  end
  .
  .
end

Character.rb:

class Character < ActiveRecord::Base
  belongs_to :sociable, polymorphic: true 
  before_save do
    self.callsign.downcase!
  end
  VALID_CALLSIGN_REGEX = /\A[a-z\d\-.\_]+\z/i
  validates :callsign, presence:   true,
                       length:     { maximum: 20 },
                       format:     { with: VALID_CALLSIGN_REGEX },
                       uniqueness: { case_sensitive: false }
end

应用程序/视图/用户/ index.html.erb:

<% provide(:title, 'All users') %>
<h1>All users</h1>
<%= will_paginate %>
<ul class="users">
  <%= render @users %>
</ul>
<%= will_paginate %>

应用程序/视图/用户/ _user.html.erb:

<li>
  <%= gravatar_for_user user, size: 52 %>
  <%= link_to user.name, user %>
  <% if current_user.admin? && !current_user?(user) %>
    | <%= link_to "delete", user, method: :delete,
                                  data: { confirm: "You sure?" } %>
  <% end %>
</li>

为什么这个测试失败了?为什么self.character.callsign中的to_param无效?

1 个答案:

答案 0 :(得分:0)

这是因为我没有手动为测试/装置中的所有用户提供角色。在characters.yml中,我为每个用户创建了一个字符,并且测试通过了。