Rails 3:在表单中传递belongs_to字段,无法批量分配受保护的属性

Emi*_*che 4 ruby-on-rails-3

我有两个模型类,患者和处方,与belongs_to关系:

class Prescription
    belongs_to :patient
    ...
Run Code Online (Sandbox Code Playgroud)

我有一个用于创建新处方对象的表单,我希望它能从隐藏的字段中获取患者:

<%= form_for(@prescription) do |f| %>
...
  <%= f.hidden_field :patient_id, :value => @patient.id %>
...
Run Code Online (Sandbox Code Playgroud)

在处方控制器中,我想使用从表格中获得的参数创建一个新的处方:

  def create
    @prescription = Prescription.new(params[:prescription])
    ...
Run Code Online (Sandbox Code Playgroud)

有些东西不起作用.我可以在日志中看到患者id正在params中传递,但它没有插入到db中:

  Started POST "/prescriptions" for 127.0.0.1 at 2011-05-13 14:59:00 +0200
  Processing by PrescriptionsController#create as HTML
  Parameters: {"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"=>"Create Prescription"}
WARNING: Can't mass-assign protected attributes: patient_id
  Patient Load (0.2ms)  SELECT "patients".* FROM "patients" WHERE "patients"."id" IS NULL LIMIT 1
  AREL (0.4ms)  INSERT INTO "prescriptions" ("medicine_name", "dispense_date", "days_supply", "patient_id", "created_at", "updated_at") VALUES ('w', '2011-05-13', 2, NULL, '2011-05-13 12:59:00.690434', '2011-05-13 12:59:00.690434')

关于质量分配受保护属性的警告信息是什么意思?如何更改代码以使其有效?

Dan*_*nne 13

我想你已经错过了关于rails的一个很棒的东西,这对于这个场景真的有帮助.这就是在路由中嵌套资源的可能性.

例如,如果您的routes.rb如下所示:

resources :patients do
  resources :prescriptions
end
Run Code Online (Sandbox Code Playgroud)

这将导致控制器的url看起来像/patients/:patient_id/prescriptions/,结果是因为patient_id已经存在于url中,所以你不必有任何隐藏的表单来存储它.所以在PrescriptionsController中,create动作可能如下所示:

def create
  @patient = Patient.find(params[:patient_id])
  @prescription = @patient.prescriptions.build(params[:prescription])
Run Code Online (Sandbox Code Playgroud)

当您使用关联来"构建"实例而不是直接使用模型时,它将自动为您分配patient_id.

这可能不是你问题的确切答案,但这可能是我做的方式.


Mis*_*cha 7

'无法进行质量分配'意味着您无法像这样自动分配值:

# In the examples below @prescription.patient_id will not be set/updated
@prescription = Prescription.new(params[:prescription])
@prescription.update_attributes(params[:prescription])
Run Code Online (Sandbox Code Playgroud)

您可以通过设置解决这个:patient_id作为attr_accessible你的Prescription模型.如果这样做,请确保您了解安全风险.

attr_accessible :patient_id
Run Code Online (Sandbox Code Playgroud)

或者patient_id直接指定一个值:

@prescription.patient_id = some_value
Run Code Online (Sandbox Code Playgroud)