Rails 5 API并设计flash未定义的方法错误

时间:2016-08-24 09:16:17

标签: ruby-on-rails devise

我正试图在new rails 5 API application上设置设计。当我尝试登录时(向/v1/sign_in发送带有POST请求的正确电子邮件和密码)我收到以下错误:

NameError (undefined local variable or method `flash' for #<SessionsController:0x007fa0f14fd280>):

devise (4.2.0) app/controllers/devise_controller.rb:157:in `set_flash_message'
devise (4.2.0) app/controllers/devise_controller.rb:164:in `set_flash_message!'
devise (4.2.0) app/controllers/devise/sessions_controller.rb:18:in `create'
actionpack (5.0.0) lib/action_controller/metal/basic_implicit_render.rb:4:in `send_action'
actionpack (5.0.0) lib/abstract_controller/base.rb:188:in `process_action'
actionpack (5.0.0) lib/action_controller/metal/rendering.rb:30:in `process_action'
actionpack (5.0.0) lib/abstract_controller/callbacks.rb:20:in `block in process_action'
activesupport (5.0.0) lib/active_support/callbacks.rb:126:in `call'
activesupport (5.0.0) lib/active_support/callbacks.rb:506:in `block (2 levels) in compile'
activesupport (5.0.0) lib/active_support/callbacks.rb:455:in `call'
activesupport (5.0.0) lib/active_support/callbacks.rb:101:in `__run_callbacks__'
activesupport (5.0.0) lib/active_support/callbacks.rb:750:in `_run_process_action_callbacks'
activesupport (5.0.0) lib/active_support/callbacks.rb:90:in `run_callbacks'
actionpack (5.0.0) lib/abstract_controller/callbacks.rb:19:in `process_action'
actionpack (5.0.0) lib/action_controller/metal/rescue.rb:20:in `process_action'
actionpack (5.0.0) lib/action_controller/metal/instrumentation.rb:32:in `block in process_action'
activesupport (5.0.0) lib/active_support/notifications.rb:164:in `block in instrument'
activesupport (5.0.0) lib/active_support/notifications/instrumenter.rb:21:in `instrument'
activesupport (5.0.0) lib/active_support/notifications.rb:164:in `instrument'
actionpack (5.0.0) lib/action_controller/metal/instrumentation.rb:30:in `process_action'
actionpack (5.0.0) lib/action_controller/metal/params_wrapper.rb:248:in `process_action'
activerecord (5.0.0) lib/active_record/railties/controller_runtime.rb:18:in `process_action'
actionpack (5.0.0) lib/abstract_controller/base.rb:126:in `process'
actionpack (5.0.0) lib/action_controller/metal.rb:190:in `dispatch'
actionpack (5.0.0) lib/action_controller/metal.rb:262:in `dispatch'
actionpack (5.0.0) lib/action_dispatch/routing/route_set.rb:50:in `dispatch'
actionpack (5.0.0) lib/action_dispatch/routing/route_set.rb:32:in `serve'
actionpack (5.0.0) lib/action_dispatch/routing/mapper.rb:16:in `block in <class:Constraints>'
actionpack (5.0.0) lib/action_dispatch/routing/mapper.rb:46:in `serve'
actionpack (5.0.0) lib/action_dispatch/journey/router.rb:39:in `block in serve'
actionpack (5.0.0) lib/action_dispatch/journey/router.rb:26:in `each'
actionpack (5.0.0) lib/action_dispatch/journey/router.rb:26:in `serve'
actionpack (5.0.0) lib/action_dispatch/routing/route_set.rb:725:in `call'
bullet (5.2.0) lib/bullet/rack.rb:12:in `call'
warden (1.2.6) lib/warden/manager.rb:35:in `block in call'
warden (1.2.6) lib/warden/manager.rb:34:in `catch'
warden (1.2.6) lib/warden/manager.rb:34:in `call'
rack (2.0.1) lib/rack/etag.rb:25:in `call'
rack (2.0.1) lib/rack/conditional_get.rb:38:in `call'
rack (2.0.1) lib/rack/head.rb:12:in `call'
activerecord (5.0.0) lib/active_record/migration.rb:552:in `call'
actionpack (5.0.0) lib/action_dispatch/middleware/callbacks.rb:38:in `block in call'
activesupport (5.0.0) lib/active_support/callbacks.rb:97:in `__run_callbacks__'
activesupport (5.0.0) lib/active_support/callbacks.rb:750:in `_run_call_callbacks'
activesupport (5.0.0) lib/active_support/callbacks.rb:90:in `run_callbacks'
actionpack (5.0.0) lib/action_dispatch/middleware/callbacks.rb:36:in `call'
actionpack (5.0.0) lib/action_dispatch/middleware/executor.rb:12:in `call'
actionpack (5.0.0) lib/action_dispatch/middleware/remote_ip.rb:79:in `call'
actionpack (5.0.0) lib/action_dispatch/middleware/debug_exceptions.rb:49:in `call'
actionpack (5.0.0) lib/action_dispatch/middleware/show_exceptions.rb:31:in `call'
railties (5.0.0) lib/rails/rack/logger.rb:36:in `call_app'
railties (5.0.0) lib/rails/rack/logger.rb:24:in `block in call'
activesupport (5.0.0) lib/active_support/tagged_logging.rb:70:in `block in tagged'
activesupport (5.0.0) lib/active_support/tagged_logging.rb:26:in `tagged'
activesupport (5.0.0) lib/active_support/tagged_logging.rb:70:in `tagged'
railties (5.0.0) lib/rails/rack/logger.rb:24:in `call'
request_store (1.3.1) lib/request_store/middleware.rb:9:in `call'
actionpack (5.0.0) lib/action_dispatch/middleware/request_id.rb:24:in `call'
rack (2.0.1) lib/rack/runtime.rb:22:in `call'
activesupport (5.0.0) lib/active_support/cache/strategy/local_cache_middleware.rb:28:in `call'
actionpack (5.0.0) lib/action_dispatch/middleware/executor.rb:12:in `call'
actionpack (5.0.0) lib/action_dispatch/middleware/static.rb:136:in `call'
rack (2.0.1) lib/rack/sendfile.rb:111:in `call'
rack-cors (0.4.0) lib/rack/cors.rb:80:in `call'
railties (5.0.0) lib/rails/engine.rb:522:in `call'
puma (3.6.0) lib/puma/configuration.rb:225:in `call'
puma (3.6.0) lib/puma/server.rb:578:in `handle_request'
puma (3.6.0) lib/puma/server.rb:415:in `process_client'
puma (3.6.0) lib/puma/server.rb:275:in `block in run'
puma (3.6.0) lib/puma/thread_pool.rb:116:in `block in spawn_thread'

我已经尝试了一些修复方法,比如在这里添加flash中间件: https://github.com/johndel/rails5-api-test/blob/master/config/application.rb#L44。我还尝试在开头添加此代码:config.middleware.insert_before(Rack::Sendfile, ActionDispatch::Flash)但仍然没有运气。知道为什么这不起作用吗?

如果您设置上述应用程序,播种它并尝试运行此命令,则可以重现它: curl -X POST -F "user[email]=istoselidas@gmail.com" -F "user[password]=example" localhost:3000/v1/sign_in

更新 似乎sign_in.json开箱即用,但password/edit.json存在一个问题,这似乎与设计有关(它在此控制器上以不同的方式接近它)。

2 个答案:

答案 0 :(得分:6)

如果你真的想保留Flash,

添加中间件确实是必要的。您还需要在SessionsController中加入Flash模块。模块Flash显然隐含了对Helpers的依赖,所以也包括它。

class SessionsController < Devise::SessionsController
  include ActionController::Helpers
  include ActionController::Flash
  ...

请注意,Devise允许其控制器继承自ApplicationController,并且该控制器继承自ActionController::API,这比通常的父类ActionController::Base更轻薄。

但是,你不必

Devise实际上知道所谓的导航格式。通常,这只是:html(如果没有指定其他格式,它也恰好是请求的默认格式。)

如果您在请求中明确使用:json格式,设计将非常智能,并且不会添加闪烁。

为此,您必须撤消所做的配置:您声明:json为导航格式。唐&#39;吨。在设计初始值设定项中还原该行:

config.navigational_formats = [:json]  # THIS IS BAD

然后,在您的请求中使用额外的.json后缀,所有内容都将按预期工作:

curl -X POST -F "user[email]=istoselidas@gmail.com" -F "user[password]=example" localhost:3000/v1/sign_in.json

你也可以摆脱Flash中间件。

对扩展问题的扩展答案:password / edit.json

在设置Flash消息时,Devise的PasswordsController似乎尊重非导航格式。到目前为止,这可能还不错,因为没有人关心使用JSON API进行newedit操作。您的规范中确保这些操作无法访问,这是完全合法的。

据我了解,这是Devise中的一个错误。让我们设计一个拉取请求来修复它! :)

您的PasswordsController通过覆盖Devise::PasswordsControllernew行动来专攻edit。您仍然会收到错误的原因是有害代码位于名为before_filter的{​​{1}}中。

因此,为您提供快速而干净的解决方案是添加自己的过滤器。您可以使用assert_reset_token_passed方法。由于该方法呈现某些东西,它将阻止Devise的过滤器被执行。 使用这种方法,您也不需要再次覆盖操作方法。

json_not_found

答案 1 :(得分:1)

这是一个有效的丑陋修复:覆盖SessionController的create方法,从原始方法复制代码并删除设置flash消息的行:

SELECT 
   FriendlyFunctionCode, 
   MAX(MemberFirmId) as MemberFirmId, 
   MAX(FunctionLevel3Desc) as FuncationLevel3Desc
INTO #StagingTable
FROM
   FirmFunction
GROUP BY
   FriendlyFunctionCode