【问题标题】:Devise generated mailer URLs with devise_for in Rails scopes在 Rails 范围内使用 devise_for 设计生成的邮件 URL
【发布时间】:2018-10-18 00:12:57
【问题描述】:

我正在使用 Javascript 框架构建 Rails 应用程序,因此 Rails 提供后端 API。

目前,该应用只是实现所有设计视图和操作。

为此,Rails 应用程序仅接受对其/api/ URL 的 JSON 调用,并要求 Devise 仅使用 JSON 调用,因此我将它们定义如下:

Rails.application.routes.draw do
  scope :api, module: :api, constraints: { format: 'json' } do
    devise_for :users, controllers: {
      confirmations: 'devise/confirmations',
      registrations: 'devise/registrations',
      sessions: 'sessions'
    }

    resources :users
  end

  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
  root to: 'home#index'
  get '*path', to: 'home#index'
end

解释这里发生了什么:

  • 第一部分是定义 API URL,包括设计 URL,并定义 API 资源(目前仅 :users)
  • 然后定义root路由
  • 最后将所有调用转发到 Javascript 路由器(允许管理页面重新加载或电子邮件链接等外部链接)。

除帐户确认电子邮件链接外,一切正常。 发送的确认电子邮件包含一个包含/api/ (http://localhost:3001/api/users/confirmation?confirmation_token=XLDVqqMZwXg6dszyV_nc) 的链接,但它应该没有(预期 URL:http://localhost:3001/users/confirmation?confirmation_token=XLDVqqMZwXg6dszyV_nc)。

我怎样才能设计发送没有/api/ 部分的确认电子邮件(和所有其他电子邮件)?

更新

深入查看设计源代码,我发现the confirmation mailer view template 使用的是confirmation_url Rails 命名路由,这是正确的。

在我的情况下,我需要将所有设计路由限制为 /api/ 路由和 JSON 格式,除了少数要定义 2 次的路由:第一次超出 HTML 中的 /api/ 范围格式(将被转发到我的 JavaScript 应用程序),以及 /api/ 范围内的第二条路由,该路由将由 JavaScript 应用程序调用。

示例:预期的帐户创建确认执行堆栈

  1. Rails 接收到/users/confirmation?confirmation_token=XLDVqqMZwXg6dszyV_nc 的请求
  2. Rails 将请求转发到 Javascript 路由器
  3. Javascript框架加载相应页面
  4. Javascript 页面加载一个服务,该服务将调用/api/users/confirmation?confirmation_token=XLDVqqMZwXg6dszyV_nc Devise 路由来确认帐户

【问题讨论】:

    标签: ruby-on-rails devise


    【解决方案1】:

    您应该能够在初始 API 路由之后简单地添加两个附加路由。像这样:

    Rails.application.routes.draw do
      scope :api, module: :api, constraints: { format: 'json' } do
        devise_for :users, controllers: {
          confirmations: 'devise/confirmations',
          registrations: 'devise/registrations',
          sessions: 'sessions'
        }
    
        resources :users
      end
    
      devise_for :users, controllers: {
        confirmations: 'devise/confirmations',
        registrations: 'devise/registrations'
      }
    
      root to: 'home#index'
      get '*path', to: 'home#index'
    end
    

    如果不看前端代码就很难确定,但两条路线都可以。

    【讨论】:

    • 感谢您的回答。我会试一试,但我的第一个想法是这也将接受 HTTP 路由来访问 HTML 设计页面并确认帐户,还是我遗漏了什么?
    • 好的,但我不想这样。我希望用户只通过 Javascript 应用程序来呈现视图,而不是通过设计视图。
    • 如果您不想要这些路由,只需将它们重定向到控制器级别的 api 路由即可。如果您使用的是 SPA,它应该重定向到路由索引,然后 SPA 路由工具处理显示正确的页面。
    【解决方案2】:

    有两种方法可以解决您的问题。

    1. 将电子邮件中的链接设为json 格式(末尾有“.json”)

    或

    1. 允许通过html 提供来自电子邮件的链接的操作(无format: 'json' 约束)。

    此示例显示如何为电子邮件确认操作执行此操作。

    scope :api, module: :api, constraints: { format: 'json' } do
      # skip routes generation for `confirmations` controller
      devise_for :users, skip: [:confirmations]
    
      # add allowed `confirmations` actions manually (all except for `show`)
      as :user do
        get 'confirmation/new', to: 'devise/confirmations#new', as: :new_user_confirmation
        post 'confirmation', to: 'devise/confirmations#create'
      end
    end
    
    # add `confirmations#show` action outside of `/api` scope to be available from email link by `html`
    as :user do
      get 'confirmation', to: 'devise/confirmations#show', as: :user_confirmation
    end
    

    如果您不想使用 Devise 的 HTML 视图和操作,您可以自定义 Devise 控制器或编写自己的控制器。这个例子展示了如何自定义设计确认控制器:

    # app/controllers/confirmations_controller.rb
    class ConfirmationsController < Devise::ConfirmationsController
      def show
        # do whatever you want
      end
    end 
    
    # config/routes.rb
    scope :api, module: :api, constraints: { format: 'json' } do
      # tell Devise to use your custom confirmations controller
      devise_for :users, controllers: {confirmations: "confirmations"}
    end
    

    更新

    另外,如果您希望您的电子邮件链接与 Devise API 无关,您可以自定义 Devise 邮件程序视图以更改电子邮件文本并将您需要的链接放在那里。

    rails generate devise:views 命令将生成标准的设计视图,包括您可以自定义的邮件模板。

    【讨论】:

    • 像其他答案一样,这将使用 Devise 的 HTML 视图和操作,而我希望我的 Javascript 应用程序处理所有视图部分,并让后面 (/api/) 处理操作。我不想允许确认操作,我希望它们成为我的后端 API 的一部分,而我的前端管理所有视图。
    • 第一个选项呢? (“.json”链接)
    • 嗯,我不明白。为什么使用 JSON 和 HTML 格式会有帮助? Javascript 应用使用 JSON 与 API 对话,用户使用 HTML 访问应用。
    • 更新了答案以解释如何不使用设计视图和操作。
    • 抱歉,我好像不太清楚。我想要的只是 Devise 是我的 API(注册用户等)的一部分,它现在已经可以使用了,我希望我的 Javascript 应用程序能够管理所有视图内容。我的问题是来自 Devise 发送的电子邮件的链接的 URL 包括 /api/ 部分,我不希望将调用重定向到 Javascript 应用程序,并通过 API Devise 调用 JS 应用程序。是不是更清楚了?
    猜你喜欢
    • 1970-01-01
    • 2015-01-05
    • 1970-01-01
    • 1970-01-01
    • 2021-08-19
    • 2013-07-23
    • 2015-08-27
    • 1970-01-01
    • 2012-05-13
    相关资源
    最近更新 更多