2015-10-11 29 views
1

我正在努力处理Hartl教程的一个问题(我添加了自己的自定义需求,即用户属于公司,创建窗体是公司#新)。现在一切正常,如密码重置等。除了一件事是activation_token方法。hartl教程第10章 - 无法找到ID

现在我试着调试静下心来,这是问题的确切行,它是这一个:

@user.activation_token 

当我尝试打印出来只是一般的登录用户是空白。现在准确的错误我得到的是:

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

请求参数如下:

"company"=>{"users_attributes"=>{"0"=>{"first_name"=>"demo", "last_name"=>"demo", "email"=>"[email protected]", "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#创建看起来像这样:

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 

我公司PARAMS:

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为零的图片,但它发现了@user对象。

+0

请显示您的'company_params'。我想你可能会错过允许用户在那里使用'id'。 – IngoAlbers

+0

好吧,我已更新以包含我的公司参数。不过,我认为这个问题可能与activation_token –

+0

有关,你可以在哪里调用你的'create_activation_digest'方法? – IngoAlbers

回答

1

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

的问题是你填充edit_activations_path@user.activation_token(其中不包括id),当该路径需要id

您应将其更改为:

<%= link_to "Activate", edit_account_activation_url @user %> 

根据你的路由(我已经低于改善),并通过对象路由行动的Rails的标准做法意味着你应该通过整个对象,并让Rails确定具体细节。

您的错误指出它的id未被传递 - 向我们显示如果您通过@user对象而不是@user.activation_token,它将使Rails具有使用它的能力。

唯一需要注意的是,您可能会在您的Activations控制器中呼叫activation_tokenemail。如果是这样的话,你需要重新修改你的路由接受令牌和电子邮件分别为(如下图):


有许多改进,你可以让你的代码:

-

你的路线可制成高效得多:

#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资源... IE将期望id制定路线。典型的ID将是对象的primary_key,您想要使用activation_token。为了解决这个问题,你应该使用下列内容:

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

这将仍然接受PARAMS为:id(需要)和: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 
相关问题