【问题标题】:How to change the default json response in devise to custom response?如何将设计中的默认 json 响应更改为自定义响应?
【发布时间】:2012-11-27 05:33:45
【问题描述】:

如果由于某种原因无法创建用户,我使用设计进行身份验证和注册控制器,那么它会产生 json 响应

{"email":["已被占用"],"password":["不匹配 确认"],"用户名":["已被占用"]}

但我希望将其更改为以下

{"error":{"email":{"已被占用"},"password":{"没有 匹配确认"},"用户名":{"已被占用"}}}

我该怎么做?

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 json devise


    【解决方案1】:

    作为参考,以防其他人在寻找如何在使用 Devise 尝试登录失败时自定义 json 错误响应时偶然发现此问题,关键是使用您自己的自定义 FailureApp 实现。 (您也可以使用这种方法来覆盖某些重定向行为。)

    class CustomFailureApp < Devise::FailureApp
      def respond
        if request.format == :json
          json_error_response
        else
          super
        end
      end
    
      def json_error_response
        self.status = 401
        self.content_type = "application/json"
        self.response_body = [ { message: "Your email or password is incorrect."} ].to_json
      end
    end
    

    在您的 devise.rb 中,查找 config.warden 部分:

      config.warden do |manager|
        manager.failure_app = CustomFailureApp
      end
    

    一些相关信息:

    起初我以为我必须重写Devise::SessionsController,可能使用传递给warden.authenticate!recall 选项,但正如here 所述,“API 请求不会调用recall,仅用于导航请求。如果你想自定义 http 状态码,在失败的应用层面这样做会更好。”

    还有https://github.com/plataformatec/devise/wiki/How-To%3a-Redirect-to-a-specific-page-when-the-user-can-not-be-authenticated

    【讨论】:

      【解决方案2】:

      @quix answer 扩展(我不把它作为评论留下,因为它有格式问题)。

      您也可以尽量减少覆盖,只需重新定义http_auth_body 方法:

      class CustomFailureApp < Devise::FailureApp
        def http_auth_body
          return super unless request_format == :json
          {
            success: false,
            error: i18n_message
          }.to_json
        end
      end
      

      【讨论】:

      • 应该是i18n_message 而不是i18_message
      • 现在已修复
      【解决方案3】:

      您应该创建一个 json.erb 文件并在该错误中呈现它。 This 答案告诉你如何做到这一点。

      【讨论】:

      • 实际上这个“format.json { respond_with_navigational(resource) }”返回了我所说的响应,所以我怎样才能把它放在 erb 文件中,我怎样才能改变它以便它产生自定义响应?
      【解决方案4】:
      respond do |format|
          format.json { render json: {error: @your_model.errors }}
      end
      

      或者你应该试试

      respond do |format|
          format.json { render json: {error: Hash[@your_model.errors.map {|k, v| k, v[0]] } }}
      end
      

      【讨论】:

      • 实际上这个“format.json { respond_with_navigational(resource) }”返回了我所说的响应,那么如何更改它以使其产生我所要求的自定义响应?
      • 我不认为 {"email":{"has already been taken"}} 是有效的 json 格式。我想你想要的是 {"email":"has already been taken"}
      猜你喜欢
      • 2019-09-09
      • 2019-07-28
      • 2020-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-18
      • 1970-01-01
      • 2012-05-19
      相关资源
      最近更新 更多