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

在我的应用程序中,我有自动电子邮件提醒应用程序完成面试过程的下一步。 电子邮件有一个选择退出链接,单击该链接时,应该触发一个控制器操作,该操作将触发状态机事件以将其状态更改为opted_out 。 链接不起作用,并且从localhost控制台看起来似乎是因为链接仍然产生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 

这是因为这是电子邮件上下文中的链接。 它是记录在案的行为 :

方法:HTTP动词的符号 – 此修饰符将动态创建HTML表单并立即提交表单以使用指定的HTTP谓词进行处理。 有用的是让链接在危险的操作中执行POST操作,例如删除记录(搜索机器人可以在抓取您的站点时遵循这些操作)。 支持的动词有:post,:delete,:patch和:put。 请注意,如果用户禁用了JavaScript,请求将回退到使用GET。 如果使用href:’#’并且用户禁用了JavaScript,则单击该链接将无效。 如果您依赖于POST行为,则应该使用请求对象的post?,delete?,patch?或put?方法在控制器的操作中检查它。

出于安全原因,禁止在电子邮件和表单中使用可执行JavaScript。 因此,使用JS呈现表单并执行PUT请求是不可能的,因此这将回到上面引用中所述的GET

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

这不适用于电子邮件:您的网站的javascript不存在,电子邮件客户端通常不运行javascript。

在某些情况下包括实际表单,但经常不会(或显示可怕的警告) – 例如,请参阅此问题 。

遗憾的是,只有一个简单的“获取”链接没有多少选择(你当然可以进入一个确认页面,你有一个按钮/链接将触发一个post请求)。