看我的问题:
class MedicalRecord < ActiveRecord::Base
has_many :evaluations, dependent: :destroy
accepts_nested_attributes_for :evaluations, allow_destroy: true, reject_if: :all_blank
end
class Evaluation < ActiveRecord::Base
belongs_to :medical_record
has_and_belongs_to_many :edemas
validates :description, presence: true
end
我的表单显示具有多个属性的选择字段。
<%= form_for @medical_record do |f| %>
<%= f.fields_for :evaluations do |e| %>
<%= e.text_field :description %>
<%= e.collection_select :edema_ids, Edema.all.order(:title), :id, :title,
{ }, multiple: true %>
<% end %>
<% end %>
当我没有选择任何'水肿'时,表单会发送一个带有一个空字符串的数组。因此,reject_if
会返回false
,我需要填写说明字段。在这种情况下,reject_if
应该返回true
。
我可以做些什么呢?
非常感谢
答案 0 :(得分:1)
如果您的目标只是在:edema_ids
数组中没有空字符串,则可以将include_hidden: false
传递给collection_select
。
那就是说,如果你最终想要取消选择&#34;这将导致问题。现有评估的所有水肿,因为如果它的值真的为空(因为它是多选),浏览器根本不会发送:edema_ids
数组,原因大致相同。发送未经检查的复选框值。在空数组中包含空字符串是表单帮助程序处理此浏览器行为的方法。
我相信建议允许HTML表单提交空字符串数组元素(因此浏览器和Rails可以在这种情况下按预期运行),并使用ActiveRecord& {39} reject_if: :all_blank
关联:evaluations
(假设您确实正在寻找的行为)。
你可以通过在传递到控制器之后的某个时刻从:edema_ids
中删除空字符串元素而不会遇到空字符串数组挂起来实现这一点。由:all_blank
进行评估。
类似于:
# Inside MedicalRecordsController
def create
@medical_record = MedicalRecord.create(medical_record_params)
end
def update
@medical_record = MedicalRecord.find(params[:id])
@medical_record.update_attributes(medical_record_params)
end
private
def medical_record_params
# I assume you're using strong params to control what can be passed
# through the controller. If so, manipulate the params *after*
# calling .require() and .permit() on the params hash
remove_empty_string_from_edema_ids(params)
end
def remove_empty_string_from_edema_ids(params_hash) # Use a better name than this
params_hash[:evaluations].each do |evaluation|
# Don't forget to use guard clause to prevent calling a
# method on nil if :edema_ids is not present in evaluation
evaluation[:edema_ids].reject!(&:empty) if evaluation[:edema_ids]
end
end
如果:all_blank
确实全部为空,那么(或类似的,有很多方法可以实现相同的结果)会 - 除了正确导致true
返回:evaluation
之外 - 导致将真正空的数组传递给评估的edema_ids=()
方法;由于一些ActiveRecord关联魔法,这将导致从:edemas
实例中删除所有Evaluation
。
答案 1 :(得分:0)
您可能希望编写自定义reject_if
方法。如果您提供符号,ActiveRecord将在当前类中查找具有该名称的方法,并传递evaluation
的已提交属性哈希值。
class MedicalRecord < ActiveRecord::Base
accepts_nested_attributes_for :evaluations, allow_destroy: true, reject_if: :essentially_blank
def essentially_blank(attributes)
attributes[:description].blank? && attributes[:edema_ids][0].blank?
end
end
请注意,虽然[""].blank?
为false,但"".blank?
为真,这就是我获取数组的第一个对象并检查其blank
的原因。
您可以查看the Rails API以查看有关如何在reject_if
上完成自定义行为的更多示例。