无法在Rails中设置邮件程序

时间:2014-11-21 18:38:07

标签: ruby-on-rails

我正在尝试使用Rails邮件程序,但是当我尝试注册新用户并发送激活电子邮件时,我收到以下错误消息。我正在关注Hartl最新的(第3版)轨道教程的第10章,所以理论上它应该有效:

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

app/views/user_mailer/account_activation.html.erb:9:in `_app_views_user_mailer_account_activation_html_erb__1296124105699284853_2236858900'

app/mailers/user_mailer.rb:6:in `account_activation'

app/models/user.rb:82:in `send_activation_email'

app/controllers/users_controller.rb:27:in `create'

相关的代码位是:

用户模型:

class User < ActiveRecord::Base
  attr_accessor :remember_token, :activation_token
  extend FriendlyId
  friendly_id :callsign, :use => :slugged
  has_secure_password
  before_save do
    self.email.downcase!
    self.callsign.downcase!
  end
  before_create do
    :create_activation_digest
  end
  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 }
  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 }
  validates :password, length: { minimum: 6 }
  validates :slug, presence: true

  # Returns the hash digest of the given string.
  def self.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 self.new_token
    SecureRandom.urlsafe_base64
  end

  # Remembers a user in the database for use in persistent sessions.
  def remember
    self.remember_token = User.new_token
    update_attribute(:remember_digest, User.digest(remember_token))
  end

  # Forgets a user.
  def forget
    update_attribute(:remember_digest, nil)
  end

  # Returns true if the given token matches the digest.
  def authenticated?(attribute, token)
    digest = send("#{attribute}_digest")
    return false if digest.nil?
    BCrypt::Password.new(digest).is_password?(token)
  end

  # Activates an account.
  def activate
    update_attribute(:activated,    true)
    update_attribute(:activated_at, Time.zone.now)
  end

  # Sends activation email.
  def send_activation_email
    UserMailer.account_activation(self).deliver_now
  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

end

用户控制器:

class UsersController < ApplicationController

  before_action :logged_in_user,     only: [:index, :show, :edit, :update, :destroy]
  before_action :non_logged_in_user, only: [:new, :create]
  before_action :correct_user,       only: [:edit, :update]
  before_action :admin_user,         only: :destroy

  def index
    @users = User.paginate(page: params[:page])
  end

  def show
    @user = User.friendly.find(params[:id])
    @page_name = "user_page"
  end

  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)
    if @user.save
      @user.send_activation_email
      flash[:info] = "Please check your email to activate your account."
      redirect_to root_url      
    else
      render 'new'
    end
  end # create

  def destroy
    @user = User.find(params[:id])
    if ( current_user != @user )
      @user.destroy
      flash[:success] = "User deleted."
      redirect_to users_url
    else
      redirect_to @user, notice: "Suicide is not permitted, admin chappie. Hard cheese."
    end
  end

  def edit
    @user = User.find(params[:id])
  end

  def update
    @user = User.find(params[:id])
    if @user.update_attributes(user_params)
      flash[:success] = "Profile updated"
      redirect_to @user
    else
      render 'edit'
    end
  end # update

  private

    def user_params
      params.require(:user).permit(:name, :email, :callsign, :password, :password_confirmation)
    end

    # Before filters

    def non_logged_in_user
      if logged_in?
        redirect_to root_url, notice: "Nice try pal. You can't create a new user 
                                       if you're already signed in."
      end
    end

    def correct_user
      @user = User.find(params[:id])
      redirect_to(root_url) unless current_user?(@user)
    end

    def admin_user
      redirect_to(root_url) unless current_user.admin?
    end

end

account_activation.html.erb:

<h1>MySite</h1>

<p>Hi <%= @user.name %>,</p>

<p>
Welcome! Click on the link below to activate your account:
</p>

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

user_mailer.rb:

class UserMailer < ActionMailer::Base
  default from: "noreply@mysite.com"

  def account_activation(user)
    @user = user
    mail to: user.email, subject: "Account activation"
  end

  def password_reset
    @greeting = "Hi"

    mail to: "to@example.org"
  end
end

routes.rb中:

Mysite::Application.routes.draw do

  resources :users
  resources :account_activations, only: [:edit]
  root                'static_pages#home'
  get    'help'    => 'static_pages#help'
  get    'about'   => 'static_pages#about'
  get    'contact' => 'static_pages#contact'
  get    'signup'  => 'users#new'
  get    'login'   => 'sessions#new'
  post   'login'   => 'sessions#create'
  delete 'logout'  => 'sessions#destroy'

end

编辑: account_activations_controller.rb:

class AccountActivationsController < ApplicationController

  def edit
    user = User.find_by(email: params[:email])
    if user && !user.activated? && user.authenticated?(:activation, params[:id])
      user.activate
      log_in user
      flash[:success] = "Account activated!"
      redirect_to user
    else
      flash[:danger] = "Invalid activation link"
      redirect_to root_url
    end
  end

end

2 个答案:

答案 0 :(得分:1)

我建议在路由文件中使用它而不是资源:

get 'account_activation', "account_activations#edit", :as => :edit_account_activation

......并在那里处理秘密令牌和电子邮件地址参数。

目前问题是您没有控制器操作来匹配您在account_activation.html.erb中使用的路线

答案 1 :(得分:0)

发现错误。 问题是User类中的这段代码:

before_create do
  :create_activation_digest
end

应该是:

before_create do
  create_activation_digest
end

或者:

before_create :create_activation_digest

小学生错误。我为浪费每个人的时间而道歉。

(因此代码:

resources :account_activations, only: [:edit]
routes.rb中的

确实创建了正确的路由)