ruby 为什么Devise注册参数有时会有不同的形式?

y53ybaqx  于 9个月前  发布在  Ruby
关注(0)|答案(1)|浏览(71)

我有一个稍微定制的Devise与Rails 5应用程序的集成。我继承了Devise::RegistrationsController,并为User资源实现了自己的create操作,而不是调用super
在开发的所有时间里,以及在生产的大部分时间里,表单中的params都是这样的:

{
  "utf8"=>"✓",
  "authenticity_token"=>"***",
  "user"=> {
    "email"=>"[email protected]",
    "password"=>"[FILTERED]",
    "password_confirmation"=>"[FILTERED]"
  },
  "commit"=>"Create account"
}

字符串
但在少数情况下,仅在生产环境中,params看起来像这样:

{
  "utf8"=>"✓",
  "authenticity_token"=>"***",
  "user[email]"=>"[email protected]",
  "user[password]"=>"[FILTERED]",
  "user[password_confirmation]"=>"[FILTERED]",
  "commit"=>"Create account",
  "registration"=> {
    "user[email]"=>"[email protected]",
    "user[password]"=>"[FILTERED]",
    "user[password_confirmation]"=>"[FILTERED]",
    "commit"=>"Create account"
  }
}


我不知道为什么会出现第二种形式的参数。我的假设是,在某些情况下,Devise会以不同的方式处理参数。我能想到的唯一一种情况是在验证问题后重新提交,每次我尝试这样做时,参数仍然以第一种形式出现(在开发和生产中)。
create操作是在假设params[:user]有一个用户属性散列的情况下编写的,而第二种形式的情况并非如此。我可以处理这两种形式的参数,但我想了解为什么会发生这种情况,我不希望这个操作被随机不同的参数调用。
如果它是相关的,提交表单(省略样式类):

<%= form_for(@user, as: :user, url: registration_path(:user)) do |f| %>
    <div class="row">
      <%= f.label :email %>
      <%= f.email_field :email, autofocus: true %>
    </div>

    <div class="row">
      <%= f.label :password %>
      <%= f.password_field :password, autocomplete: "off" %>
    </div>

    <div class="row">
      <%= f.label :password_confirmation, 'Password confirmation' %>
      <%= f.password_field :password_confirmation, autocomplete: "off" %>
    </div>

    <div class="row">
      <div>
        <%= f.submit "Create account" %>
      </div>
    </div>
  <% end %>


额外的日志记录证实了一些有趣的事情:被窃听的请求的request.media_typeapplication/json(典型的请求应该是application/x-www-form-urlencoded
在我看来,表单数据是用错误的请求类型提交的,这可能解释了为什么值没有被解包(为什么我们在参数中使用user[email]作为属性名)以及为什么我们在registration对象中 Package 参数(我为JSON启用了wrap_parameters)。
这并不能解释为什么只有一些请求被标记为这种媒体类型。

zour9fqk

zour9fqk1#

这发生在ActionController::ParamsWrapper生效时。
启用后,params Package 器将使用当前控制器的名称 Package 传入的参数(如果尚未嵌套在该名称下)。
在您的示例中,您将嵌套在user下的参数发送到名为RegistrationsController的控制器。因此,ParamsWrapper再次使用registration Package 它们。如果您将它们发送到UsersController,它们将不会更改,因为它们已经嵌套在user下。
恕我直言,这是Ruby on Rails最无用和最容易出错的神奇行为之一。我通常会立即禁用它,因为它经常会导致问题。例如,当前端不做任何嵌套,只是依赖于此功能,但后端需要重新构造并引入名称空间或重命名控制器时。

相关问题