我有两个模型类,患者和处方,具有belongs_to关系:
class Prescription
belongs_to :patient
...
我有一个用于创建新的处方对象的表单,我希望它从隐藏字段中获取患者:
<%= form_for(@prescription) do |f| %>
...
<%= f.hidden_field :patient_id, :value => @patient.id %>
...
在处方控制器中,我想使用从表单中获得的参数创建一个新处方:
def create
@prescription = Prescription.new(params[:prescription])
...
有些东西不起作用。我可以在日志中看到患者 ID 正在参数中传递,但它没有插入到数据库中:
在 2011-05-13 14:59:00 +0200 开始为 127.0.0.1 开机自检"/处方" 按处方处理控制器#创建为 HTML 参数: {"utf8"=>"✓", "authenticity_token"=>"h3rizbBoW069EfvQf6NyzH53k+g4o4XO61jeZ/GF6t0=", "prescription"=>{"medicine_name"=>"w", "dispense_date(1i)"=>"2011", "dispense_date(2i)"=>"5", "dispense_date(3i)"=>"13", "days_supply"=>"2", "patient_id"=>"1"}, "commit"=>"创建处方"}警告:无法批量分配受保护的属性:patient_id 患者负载(0.2ms) 选择"患者"。ID"为空限制 1 AREL (0.4ms) 插入"处方"("medicine_name"、"dispense_date"、"days_supply"、"patient_id"、"created_at"、"updated_at") 值("W", "2011-05-13", 2, NULL, "2011-05-13 12:59:00.690434", "2011-05-13 12:59:00.690434")
有关批量分配受保护属性的警告消息是什么意思?如何更改代码使其正常工作?
您错过了有关rails的一大优点,它在这种情况下确实会有所帮助。这就是在路由中嵌套资源的可能性。
例如,如果您的 routes.rb 如下所示:
resources :patients do
resources :prescriptions
end
这将导致控制器的 url 看起来像/patients/:patient_id/prescriptions/
,其结果是,由于 url 中已经存在patient_id,因此您不必有任何隐藏形式来存储它。因此,在您的处方控制器中,创建操作可能如下所示:
def create
@patient = Patient.find(params[:patient_id])
@prescription = @patient.prescriptions.build(params[:prescription])
当您使用关联来"构建"实例而不是直接使用模型时,它将自动为您分配patient_id。
这可能不是您问题的确切答案,但这可能是我的做法。
"无法批量分配"意味着您无法像这样自动分配值:
# In the examples below @prescription.patient_id will not be set/updated
@prescription = Prescription.new(params[:prescription])
@prescription.update_attributes(params[:prescription])
您可以通过在Prescription
模型中将:patient_id
设置为attr_accessible
来解决此问题。如果这样做,请确保您了解安全风险。
attr_accessible :patient_id
或者直接为patient_id
赋值:
@prescription.patient_id = some_value
我在上面的代码片段中放得不够多。事实证明,在我的模型中,问题是由于这个原因造成的:
class Prescription:
belongs_to :patient
attr_accessible :medicine_name, :dispense_date, :days_supply
所以我在attr_accessible列表中没有耐心,这导致了错误消息。我真的不明白attr_accessible需要做什么,如果我删除它,一切都会起作用。
感谢您的评论,尤其是关于嵌套资源的评论,我会研究一下。