Rails params return 在更新模型的哈希属性时为 nil
Rails params return as nil when updating a model's hash attribute
我的应用程序中有一个名为 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">
知道我的问题是什么吗?一整天都在为这个问题挠头。
为了简单起见,我会考虑使用 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
我的应用程序中有一个名为 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">
知道我的问题是什么吗?一整天都在为这个问题挠头。
为了简单起见,我会考虑使用 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