【问题标题】:Rails params return as nil when updating a model's hash attribute更新模型的哈希属性时,Rails 参数返回 nil
【发布时间】:2019-06-30 01:04:18
【问题描述】:

我的应用程序中有一个模型,名为 Admin

这个Admin 可以有多个电子邮件,这些电子邮件存储在一个名为emails 的哈希中。例如,

{"sales"=>{"general"=>"sales@shop.com"},"support"=>{"general"=>"support@shop.com"}}

在创建访问这些特定电子邮件的表单时,我可以让每封电子邮件出现在输入中,但是当我尝试更新模式时,没有任何变化,因为我的 admin_params[:emails]nil

以下是我在edit.html.erb 文件中的表格:

<%= form_for @admin do |f| %>
    <dt class="col-sm-10">Admin Emails</dt>
    <%  @admin.emails.each do |type, subtype|%>
          <dt class="col-sm-10"> <%= f.label type %> </dt>
          <% if @admin.emails.include?(type) %>
            <% @admin.emails[type].each do |subtype_label, subtype_email| %>
              <%= f.fields :emails do |field| %>
                <dd class="col-sm-5"><%= field.label subtype_label %></dd>
                <dd class="col-sm-5"><%= field.text_field subtype_label, :value => subtype_email %></dd>
              <% end %>
            <% end %>
          <% end %>
    <% end %>

这里是 set_admin 方法,在除 index 之外的任何其他方法之前调用:

def admin_params
  params.require(:admin).permit(:name, :emails)
end

这是我的更新方法:

def update
  binding.pry
  @admin.update(
    name: admin_params[:name],
    emails: admin_params[:emails]
  )

  redirect_to admin_path(@admin)
end

最后,这是在特定输入上呈现的 HTML:

<input value="emails" type="text" name="admin[emails][general]" id="admin_emails_general">

知道我的问题是什么吗?一整天都在挠头。

【问题讨论】:

  • 你能补充一下参数是如何在更新方法中传递的吗?
  • @joseph 你在update 方法中得到了什么参数请贴出来
  • @admin.emails.include?(type) 没有意义,因为typeemail 哈希属性的关键
  • 在代码中使用 @admin.emails[type].each 不好,因为您可以使用 subtype.each
  • 试试params.require(:admin).permit(:name, :emails =&gt; [])

标签: ruby-on-rails hash textfield strong-parameters form-helpers


【解决方案1】:

为了简单起见,我会考虑使用 Rails 方式:

class Admin < ApplicationRecord
  has_many :emails, dependent: :destroy
  accepts_nested_attributes_for :emails, 
    reject_if: proc { |attributes| attributes['email'].blank? }
end

class Email < ApplicationRecord
  enum type: [:work, :home]
  belongs_to :admin
end

这只是一个普通的一对多关联和accepts_nested_attributes_for

<%= form_for(@admin) do |f| %>
  <%= f.fields_for :emails do |ef| %>
     # ...
     <%= ef.select :type, Email.types.keys.map {|k| [k.humanize, k] } %>
     <%= ef.text_field :email %>
  <% end %>
  # ...
<% end %>

fields_for 通过命名输入admin[emails_attributes][][email]admin[emails_attributes][][type] 在参数中创建一个哈希数组。

您的解决方案是覆盖相同的单个参数。虽然您可以通过手动设置 name 属性来解决这个问题,但我会考虑是否值得付出努力。

要将嵌套参数列入白名单,请传递一个包含要列入白名单的键的数组:

def admin_params
  params.require(:admin).permit(:name, emails_attributes: [:type, :email])
end

【讨论】:

    猜你喜欢
    • 2017-03-01
    • 1970-01-01
    • 2011-03-16
    • 2021-01-22
    • 2012-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-23
    相关资源
    最近更新 更多