Rails 3.2 `link_to`(在电子邮件中)与`method: :put`仍在产生GET请求

Posted

技术标签:

【中文标题】Rails 3.2 `link_to`(在电子邮件中)与`method: :put`仍在产生GET请求【英文标题】:Rails 3.2 `link_to` (in email) with `method: :put` still producing GET request 【发布时间】:2014-10-23 17:51:48 【问题描述】:

在我的应用程序中,我有自动电子邮件提醒应用程序完成面试过程的下一步。该电子邮件有一个退出链接,单击该链接时,应该会触发一个触发状态机事件以将其状态更改为opted_out 的控制器操作。该链接不起作用,从本地主机控制台看来,这似乎是因为该链接仍在产生一个 GET 请求,没有路由(错误是ActionController::RoutingError (Not Found):)。

这是显示不需要的 GET 请求的控制台:

Started GET "/worker/application/opt_out.1" for 10.0.2.2 at 2014-08-29 17:08:06 +0000
Processing by LandingController#show as 
  Parameters: "category"=>"worker/application", "location"=>"opt_out"

这是链接:

link_to 'stop getting these reminders', opt_out_worker_application_url(@worker), method: :put, style: 'background-color: #fff; color: #56A0D3; display: inline-block; margin-bottom: 5px; margin: 0px; padding: 0px; text-decoration: none'

以下是worker 命名空间的所有路由:

# routes.rb

  namespace :worker do
    resource :application, only: [:create, :new, :show] do
      member do 
        put 'opt_out' => 'application#opt_out'
      end
    end
    resources :jobs do
      member do
        post 'compete' => 'jobs#compete'
        delete 'compete' => 'jobs#withdraw'
      end
      resources :comments, only: [:create]
      resources :timesheets, only: [:create, :new, :show]
    end
    resources :banks, only: [:create, :new, :destroy]
    scope 'money' do
      root to: 'money#index', as: 'money'
      post 'withdraw' => 'money#withdraw', as: 'money_withdraw'
    end
    get 'profile' => 'profiles#show'
    root to: 'jobs#index'
  end

这是控制器动作:

# applications_controller.rb

      def opt_out
        @worker = Worker.find(params[:id])
        if @worker.interview_requested? or @worker.onboarding_requested?
          if @worker.fire_state_event(:opt_out)
            AdminsMailer.sweeper_opted_out(@worker.id)
            redirect_to root_url, notice: "You have successfully opted out of the application process. We're sorry to see you go, and hope you'll consider returning in the future!"
          else
            redirect_to root_url, alert: "There was a problem. Please contact Support if you need further assistance."
          end
        else
          redirect_to root_url, alert: "There was a problem. Please contact Support if you need further assistance."
        end
      end

这里是rake routes

opt_out_worker_application PUT    /worker/application/opt_out(.:format)           worker/application#opt_out
                worker_application POST   /worker/application(.:format)                   worker/applications#create
            new_worker_application GET    /worker/application/new(.:format)               worker/applications#new
                                   GET    /worker/application(.:format)                   worker/applications#show

【问题讨论】:

link_to 怎么可能是PUTlink_to 不能有字段/表单,那么将其设置为 PUTPOST 有什么意义? 我没有关注你,因为你问了两个看起来至少是半修辞的问题。你对我应该改变什么有什么建议吗? 为什么要将 link_to 作为 PUT? 我认为我必须这样做,因为路线是PUT 路线。实际上没有对应于我链接到的控制器操作的视图。新手来了!那么删除 method: 声明会有帮助吗? 是的,只需将其删除.. 如果您遇到有关路由的错误,请向我显示与控制器相关的所有路由 【参考方案1】:

这是因为这是电子邮件上下文中的链接。我是documented behavior:

method: HTTP 动词的符号 - 这个修饰符将动态创建一个 html 表单并立即使用 指定的 HTTP 动词。对于让链接执行 POST 操作很有用 在删除记录等危险操作中(搜索机器人可以 在爬取您的网站时跟随)。支持的动词是 :post, :delete, :patch 和 :put。请注意,如果用户禁用了 javascript,则 请求将回退到使用 GET。如果使用 href: '#' 并且用户 已禁用 JavaScript 单击链接将无效。如果你 依赖于 POST 行为,你应该在你的 通过使用请求对象的 post 方法来执行控制器的操作? 删除?、补丁?还是放置?

出于安全原因,不允许在电子邮件和表单中使用可执行的 JavaScript。因此,不可能用 JS 渲染表单并执行PUT 请求,所以这会退回到上面引用中所述的GET

【讨论】:

谢谢。我很确定我“尝试”做的事情是可能的,因为我的管理仪表板中有类似的链接来更改 Worker 状态并且它们工作正常。无论如何,我担心会是这样。处理这个问题的最佳方法是什么?将用户带到具有相同功能的另一个按钮的页面? @sixty4bit 应该没问题。我在很多地方都看到过这种做法。【参考方案2】:

link_to 上的方法选项有效,因为您的应用包含一些拦截链接点击的 javascript。该 javascript 使用正确的方法创建一个表单(为浏览器不支持的请求方法添加一个输入元素)并支持它。

这在电子邮件中不起作用:您网站的 javascript 不存在,并且电子邮件客户端通常不运行 javascript。

在某些情况下包含实际表单有效,但经常无效(或显示可怕的警告) - 例如,请参阅 this question。

不幸的是,除了简单的“获取”链接之外,别无选择(当然,您可以将其转到确认页面,其中有一个按钮/链接可以触发发布请求)。

【讨论】:

谢谢。我如何将 Worker 的 ID 从电子邮件视图传递到确认页面?我可以强制他们登录,但如果有其他方法,我宁愿不必这样做。 您必须在链接中放置那个或某种可识别用户的不透明令牌

以上是关于Rails 3.2 `link_to`(在电子邮件中)与`method: :put`仍在产生GET请求的主要内容,如果未能解决你的问题,请参考以下文章

在rails中带有jquery参数的link_to

Rails:禁用link_to链接不起作用但隐藏link_to工作

Rails 3.2 电子邮件在被 Sendgrid 处理之前延迟了 11 分钟

在这种情况下,如何以 RESTfully 方式使用 Rails 帮助程序 link_to?

link_to 弹出模态 div 在 Rails 中不起作用

Rails 的 link_to 方法:GET 啥时候应该 DELETE