【问题标题】:PeopleController create action should redirect when model is validPeopleController 创建操作应在模型有效时重定向
【发布时间】:2014-02-06 17:48:09
【问题描述】:

已被赋予找出某些 rspec 测试失败的原因的任务。我没有为其中任何一个编写代码并且被卡住了。这是输出:

3) PeopleController create action should redirect when model is valid
     Failure/Error: post :create
     TypeError:
       no implicit conversion of nil into String
     # ./app/models/person.rb:24:in `digest'
     # ./app/models/person.rb:24:in `hexdigest'
     # ./app/models/person.rb:24:in `encrypt_password'
     # ./app/models/person.rb:30:in `prepare_password'
     # ./app/controllers/people_controller.rb:10:in `create'
     # ./spec/controllers/people_controller_spec.rb:20:in `block (2 levels) in <top (required)>'

这里是 people_controller_spec:

require File.dirname(__FILE__) + '/../spec_helper'

describe PeopleController do
  fixtures :all
  render_views

  it "new action should render new template" do
    get :new
    response.should render_template(:new)
  end

  it "create action should render new template when model is invalid" do
    Person.any_instance.stub(:valid?).and_return(false)
    post :create
    response.should render_template(:new)
  end

  it "create action should redirect when model is valid" do
    Person.any_instance.stub(:valid?).and_return(true)
    post :create
    response.should redirect_to(root_url)
    session['person_id'].should == assigns['person'].id
  end

  it "show action should redirect when not logged in" do
    get :show, :id => "ignored"
    response.should redirect_to(login_url)
  end

  it "show action should render show template" do
    @controller.stub(:current_user).and_return(Person.first)
    get :show, :id => "ignored"
    response.should render_template(:show)
  end

end

这是失败的 people_controller 的代码块:

def create
    @person = Person.new(:username => params[:username], :password => params[:password], :first_name => params[:first_name], :last_name => params[:last_name])
    if @person.save
      session[:person_id] = @person.id
      if Invite.where(:ad_username => @person.username).count != 0
        organization = Organization.find(Invite.where(:ad_username => @person.username).first.organization_id)
        Affiliation.create!(:organization_id => organization.id, :person_id => @person.id, :affiliation_type => Affiliation::ATHLETIC_DIRECTOR)
      end
      redirect_to root_url, :notice => "Thank you for signing up! You are now logged in."
    else
      render :action => 'new'
    end
  end

这是人员模型:

class Person < ActiveRecord::Base

  # new columns need to be added here to be writable through mass assignment
  attr_accessible :username, :password, :password_confirmation, :first_name, :last_name, :cell_phone
  has_one :affiliation, :dependent => :destroy
  has_many :contacts, :dependent => :destroy

  before_save :prepare_password
  before_validation :downcase_username

  validates :username, :uniqueness => {:case_sensitive => false}
  validates_presence_of :username, :first_name, :last_name
  validates_format_of :username, :with => /^[-a-z0-9_+\.]+\@([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i, :message => " must be a valid email"
  validates_presence_of :password, :on => :create
  validates_confirmation_of :password
  validates_length_of :password, :minimum => 4

  def self.authenticate(login, pass)
    person = find_by_username(login.downcase)
    return person if person && person.password == person.encrypt_password(pass)
  end

  def encrypt_password(pass)
    Digest::SHA1.hexdigest(pass)
  end

  private

  def prepare_password
    self.password = encrypt_password(password)
  end

  def downcase_username
    self.username = self.username.downcase if self.username.present?
  end

end

我不知道这是哪里出错了。

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-3 rspec


    【解决方案1】:

    错误是由 nil :password 引起的。似乎 before_save :prepare_password 过滤器正在运行并抛出该错误。但是使用 before_save 似乎是不正确的,因为每次更新时都会发生这种情况,每次都重新加密他们的密码。将其更改为 before_create 使其只发生一次。如果它仍然抛出错误,您可以采取一些措施来解决它:

    def encrypt_password(pass)
      Digest::SHA1.hexdigest(pass.to_s) # will change nils into strings and this won't blow up
    end
    

    或在您的测试用例中添加密码参数:

    it "create action should render new template when model is invalid" do
      Person.any_instance.stub(:valid?).and_return(false)
      post :create, :password => "" # invalid password
      response.should render_template(:new)
    end
    

    这样控制器将接收params[:password]并将字符串传递给Person.new

    【讨论】:

      猜你喜欢
      • 2011-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-16
      • 2014-10-02
      • 1970-01-01
      相关资源
      最近更新 更多