Rails - 电子邮件确认链接,显示“未知操作”错误

时间:2013-04-29 07:07:49

标签: ruby-on-rails ruby ruby-on-rails-3 authentication email-validation

我需要一些帮助。我想:

  1. 发送电子邮件并附上链接。
  2. 将链接设置为user.email_activation_token = true
  3. 然后重定向到主页。
  4. 目前我有一个链接到电子邮件,但它给了我这个错误。 (我正在使用HAML顺便说一句。)

    编辑:目前没有视图。

    未知行动

    The action 'show' could not be found for UsersController
    

    user_mailer文件/ registration_confirmation的

    Confirm your email address please!
    
    = accept_invitation_users_url({:token=>@user.email_activation_token})
    

    users_controller.rb

    class UsersController < ApplicationController
      def new
        @user = User.new
      end
      def create
        @user = User.new(params[:user])
        if @user.save
          UserMailer.registration_confirmation(@user).deliver
            redirect_to root_url, :notice => "Signed up!"
        else
            render "new"
        end
    
        def accept_invitation
            @user = User.find_by_email_activation_token!(params[:token])
            @user.email_activation_token = true
            redirect_to root_url, :notice => "Email has been verified."
        end
      end
    end
    

    email_activations_controller.rb

    class EmailActivationsController < ApplicationController
        def edit
            @user = User.find_by_email_activation_token!(params[:id])
            @user.email_activation_token = true
            save!
            redirect_to root_url, :notice => "Email has been verified."
        end
        def new
            @user = User.find_by_email_activation_token!(params[:id])
        end
    
        def edit
        end
    end
    

    user.rb(用户模型)

        class User < ActiveRecord::Base
          attr_accessible :email, :password, :password_confirmation
    
          attr_accessor :password
          before_save :encrypt_password
          before_save { |user| user.email = email.downcase }
          before_create { generate_token(:auth_token) }
          # before_create { generate_token(:email_activation_token) }
    
          VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
          VALID_PASSWORD_REGEX = /^(?=.*[a-zA-Z])(?=.*[0-9]).{6,}$/
          validates_confirmation_of :password
          validates :password, :on => :create, presence: true, format: { with: VALID_PASSWORD_REGEX }
          validates :email, presence: true, format: { with: VALID_EMAIL_REGEX }, uniqueness: { case_sensitive: false }
    
      def self.authenticate(email, password)
       user = find_by_email(email)
       if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
        user
       else  
        nil
      end
    end
    
      def send_password_reset
        generate_token(:password_reset_token)
        self.password_reset_sent_at = Time.zone.now
        save!
        UserMailer.password_reset(self).deliver
      end
    
      def encrypt_password
        if password.present?
            self.password_salt = BCrypt::Engine.generate_salt
            self.password_hash = BCrypt::Engine.hash_secret(password, password_salt)
        end
      end
    
    def generate_token(column)
      begin
        self[column] = SecureRandom.urlsafe_base64
      end while User.exists?(column => self[column])
    end
    
    end
    

    的routes.rb

    LootApp::Application.routes.draw do
      get "password_resets/new"
    
      get "sessions/new"
    
      resources :users
      resources :sessions
      resources :password_resets
      resources :email_activations
    
      resources :users do
        collection do 
          get :accept_invitation
        end 
      end
    
      # get "users/new"
      get "static_pages/home"
      get "static_pages/help"
    
    
      root to: 'static_pages#home'
      match "sign_up",  to: "users#new"
      match '/help',    to: 'static_pages#help'
      match '/log_in',  to: 'sessions#new'
      match '/log_out', to: 'sessions#destroy'
    end
    

4 个答案:

答案 0 :(得分:2)

  

尝试改变这样的路线..

    resources :users do
      collection do 
        get :accept_invitation
      end 
    end

    resources :users
    resources :sessions
    resources :password_resets
    resources :email_activations

答案 1 :(得分:2)

您已拨打资源:用户两次。

删除第一个电话

答案 2 :(得分:2)

routes.rb中的用户有两条路由

删除resources :users

第一个resources users会覆盖下一个用户资源

因此应用程序不知道collectionaccept_invitation路由id 将其视为显示操作的/users/accept_invitation ,因为为该操作生成的网址将为

/users/:id

与show resources :users

的签名相匹配

删除第一个{{1}}应该可以解决问题

我也没有看到使用email_activations_controller.rb

可能是您可以安全地删除它

答案 3 :(得分:2)

为什么你在accept_invitation_users_url中传递激活令牌而不是id?当你有这个代码时:

resources :users do
  member do 
    get :accept_invitation
  end 
end

在路线中,我们假设,accept_invitation是一个Restful路线,并在其网址中提供id。见http://guides.rubyonrails.org/routing.html#adding-more-restful-actions

所以,我认为你应该这样做:

<强>的routes.rb

# resources :users ### Remove this as it is reduntant

resources :users do
  member do 
    get :accept_invitation
  end 
end

<强> user_mailer文件/ registration_confirmation的

Confirm your email address please!

= accept_invitation_users_url(@user)

<强> users_controller.rb

def accept_invitation
  @user = User.find(params[:id])
  @user.email_activation_token = true
  redirect_to root_url, :notice => "Email has been verified."
end

阅读评论后

是的,正如@Frederick Cheung在评论中所说,传递id而不是令牌会破坏发送电子邮件确认的点,并且会让人们在没有实际收到电子邮件的情况下轻松确认电子邮件地址。

所以,请参考@ PriteshJ的回答。显然,你刚刚在resources :users中添加了一行routes.rb,我从中大惊小怪:)。只需删除该行就可以了。