hartl教程第10章 - 无法找到ID

时间:2015-10-11 19:59:15

标签: ruby-on-rails

我正在努力解决Hartl教程的一个问题(我已经添加了自己的自定义需求,即用户属于公司,创建表单是#new公司。)现在一切正常,比如密码重置等。除了一件事就是activation_token方法。

现在我已经尝试调试以确定问题的确切行,这就是这个:

 @user.activation_token

当我尝试仅为登录用户打印时,它是空白的。现在我得到的准确错误是:

No route matches {:action=>"edit", :controller=>"account_activations", :email=>"ex@ex.ex", :id=>nil} missing required keys: [:id]

请求参数如下:

"company"=>{"users_attributes"=>{"0"=>{"first_name"=>"demo", "last_name"=>"demo", "email"=>"ex@ex.ex", "password"=>"demodemo"}}, "name"=>"demo"}

并且错误发生在:

<%= link_to "Activate", edit_account_activation_url(@user.activation_token, email: @user.email) %>

我的User.rb:

class User < ActiveRecord::Base
  attr_accessor :remember_token, :activation_token, :reset_token
  before_create :create_activation_digest
  ...

 class << self
    # Returns the hash digest of the given string.
    def digest(string)
      cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
                                                    BCrypt::Engine.cost
      BCrypt::Password.create(string, cost: cost)
    end

    # Returns a random token
    def new_token
      SecureRandom.urlsafe_base64
    end
 end

private

    # Creates and assigns the activation token and digest.
    def create_activation_digest
      self.activation_token  = User.new_token
      self.activation_digest = User.digest(activation_token)
    end

现在它可以在我的测试中获取ID时执行以下操作:

  def account_activation
    user = User.first
    user.activation_token = User.new_token
    UserMailer.account_activation(user)
  end

我的companycontroller #crera看起来像这样:

  def create
    @company = Company.new(company_params)
    if @company.save
      user = @company.users.first
      user.send_activation_email
      flash[:info] = "registerd and email sent"
      redirect_to root_url
    else
      flash.now[:danger] = 'issues with creating user.'
      render 'new'
    end
  end

我的公司参与:

  def company_params
    params.require(:company).permit(:name, users_attributes: [:id, :first_name, :last_name, :email, :password])
  end

路线:

Rails.application.routes.draw do
  get 'password_resets/new'

  get 'password_resets/edit'

  root    'welcome#index'
  get     'company/users' => 'companies#users'
  get     'login'         => 'sessions#new'
  post    'login'         => 'sessions#create'
  delete  'logout'        => 'sessions#destroy'
  resources :companies
  resources :users
  resources :account_activations, only: [:edit]
  resources :password_resets,     only: [:new, :create, :edit, :update]
end

注意:用户确实成功保存,公司也是如此。当我取消注释时,我也能够获得一般用户信息.activation_token我可以看到我能够从我的控制台获取电子邮件中的@ user.first_name等。

on the picture you can see @user.activation_token is nil, but it finds the user object

在图片上你可以看到@ user.activation_token是nil,但它找到了@user对象。

1 个答案:

答案 0 :(得分:1)

根据您的屏幕截图,问题不在于您的activation_token方法,因为这似乎是创建和调用的方法。

问题是,如果该路径需要edit_activations_path,则@user.activation_token使用id(不包括id)填充<%= link_to "Activate", edit_account_activation_url @user %>

您应将其更改为:

id

根据您的路由(我在下面进行了改进),以及将对象传递给路由操作的Rails标准做法意味着您应该传递整个对象,并让Rails确定具体细节。

您的错误表明它未被传递@user - 向我们显示如果您传递@user.activation_token对象而不是activation_token,它将使Rails能够使用它。

唯一需要注意的是,您可能会在email控制器中呼叫Activations #config/routes.rb root 'welcome#index' resource :company, only: [] do get :users, on: :collection end resources :companies, :users resources :account_activations, only: [:edit] resources :password_resets, only: [:new, :create, :edit, :update] resources :sessions, only: [:new, :create, :destroy], path_names: { new: "login", create: "login", destroy: "logout" } 。如果是这种情况,您需要重新设计路线以分别接受令牌和电子邮件(下方):

您可以对代码进行一些改进:

-

您的路线可以更有效率:

account_activations

现在,需要注意的重要事项是Rails资源将成为标准id资源...... IE将期望activation_token制定路线。典型ID将是对象的primary_key,您要使用<%= link_to "Activate", edit_account_activation_url(id: @user.activation_token, email: @user.email) %> 。要解决此问题,您应该使用以下内容:

:id

这仍然会接受params :email(必填)和#app/controllers/activations_controller.rb class ActivationsController < ApplicationController def edit token = params[:id] email = params[:email] end end ,但会填充您需要的数据,允许您使用:

User

-

模型调用def create_activation_digest activation_token = class.new_token activation_digest = class.digest(activation_token) end 两次。你应该拨打以下电话:

/*
 * Remember that NULL + any string = NULL.
 * Provide the concat var with a default value.
 */
DECLARE @ConCat         VARCHAR(255) = '';  
DECLARE @SampleTable    TABLE
    (
        Value   VARCHAR(5)
    )
;

-- Populate the sample table.
INSERT INTO @SampleTable (Value)
    VALUES
        ('a'),
        ('b'),
        ('c')
;

-- Concatenate the values into one string.
SELECT
    @ConCat = @ConCat + Value
FROM
    @SampleTable
;


-- Return the concatenated string
SELECT
    @ConCat
;