0

編集済み:以下のコードは、回答からの最後の提案を反映しています...

1 つのフォームから 2 つの異なるモデルに保存するのに問題があります... Rails キャスト #196 をたどろうとし、stackoverflow で他のいくつかの例を見ましたが、私の場合は少し違う…

だから、私は2つのモデルを持っています:

class Patient < ActiveRecord::Base
  attr_accessible :date_of_birth, :patient_name

  has_many :samples
end

class Sample < ActiveRecord::Base
  attr_accessible :approved, :patientID, :result, patient_attributes: [:patient_name, :date_of_birth]

  belongs_to :patient
  accepts_nested_attributes_for :patient
end

Railscasts を含む、私が見たほとんどの例で見つけたのは、患者フォーム内に新しいサンプルを作成することであり、「accepts_nestes_attributes_for」は「患者」モデル内にあります...しかし、私がやりたいことはまさに反対に、つまり、新しいサンプル フォーム内に新しい患者を作成します。

これが私の見解です。サンプルには通常の形式があり、患者の部分には部分的な形式があります。

_form.html.erb

<%= form_for(@sample) do |f| %>
  <% if @sample.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@sample.errors.count, "error") %> prohibited this sample from being saved:</h2>

      <ul>
      <% @sample.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :result %><br />
    <%= f.text_area :result %>
  </div>
  <div class="field">
    <%= f.label :approved %><br />
    <%= f.check_box :approved %>
  </div>
  <div><%= render 'patient', f: f %></div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

患者.html.erb

<%= f.fields_for :patient do |p| %>
<div class="field">
    <%= p.label :patient_name %><br />
    <%= p.text_field :patient_name %>
</div>
<div class="field">
    <%= p.label :date_of_birth %><br />
    <%= p.date_select :date_of_birth %>
</div>
<% end %>

送信ボタンをクリックすると、すべてが機能しているように見えますが、患者テーブルには何も保存されません。

ログは次のとおりです。

Started POST "/samples" for 127.0.0.1 at 2013-10-12 23:32:03 +0100
Processing by SamplesController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"13OKZ8DaGJ4zTb35q+ymSzx7r+Ipxou1u+XrR4jtyeI=", "sample"=>{"result"=>"teste 3", "approved"=>"0"}, "patient"=>{"patient_name"=>"Joao", "date_of_birth(1i)"=>"2013", "date_of_birth(2i)"=>"10", "date_of_birth(3i)"=>"10"}, "commit"=>"Create Sample"}
   (0.1ms)  begin transaction
  SQL (0.5ms)  INSERT INTO "samples" ("approved", "created_at", "patientID", "result", "updated_at") VALUES (?, ?, ?, ?, ?)  [["approved", false], ["created_at", Sat, 12 Oct 2013 22:32:03 UTC +00:00], ["patientID", nil], ["result", "teste 3"], ["updated_at", Sat, 12 Oct 2013 22:32:03 UTC +00:00]]
   (2.4ms)  commit transaction
Redirected to http://localhost:3000/samples/3
Completed 302 Found in 6ms (ActiveRecord: 2.9ms)

ログでわかるように、サンプル テーブルに保存するだけです。この方法で accept_nested_attributes_for を使用できますか? 私が望むものを達成する方法はありますか?それとも、別のアプローチを試す必要がありますか?

更新: ここに私の患者とサンプル コントローラーのコードがあります。

患者_コントローラー.rb

def new
    @patient = Patient.new

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @patient }
    end
end

def create
    @patient = Patient.new(params[:patient])

    respond_to do |format|
      if @patient.save
        format.html { redirect_to @patient, notice: 'Patient was successfully created.' }
        format.json { render json: @patient, status: :created, location: @patient }
      else
        format.html { render action: "new" }
        format.json { render json: @patient.errors, status: :unprocessable_entity }
      end
    end
end

samples_controller.rb

def new
    @sample = Sample.new
    @sample.build_patient #suggested by El Key

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @sample }
    end
end

def create
    @sample = Sample.new(params[:sample])

    respond_to do |format|
      if @sample.save
        format.html { redirect_to @sample, notice: 'Sample was successfully created.' }
        format.json { render json: @sample, status: :created, location: @sample }
      else
        format.html { render action: "new" }
        format.json { render json: @sample.errors, status: :unprocessable_entity }
      end
    end
end

El Keyの提案に従った後の更新されたログは次のとおりです。

Started POST "/samples" for 127.0.0.1 at 2013-10-17 00:20:05 +0100
Processing by SamplesController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"NZXQUdd8tQc206LdEuYF5iO5+89wlfza0VbbvgBGNuI=", "sample"=>{"result"=>"teste 9", "patientID"=>"", "approved"=>"0", "patient_attributes"=>{"patient_name"=>"Sergio", "date_of_birth(1i)"=>"2013", "date_of_birth(2i)"=>"10", "date_of_birth(3i)"=>"2"}}, "commit"=>"Create Sample"}
Completed 500 Internal Server Error in 1ms

ActiveModel::MassAssignmentSecurity::Error - Can't mass-assign protected attributes: patient_attributes:

ご覧のとおり、「保護された属性を一括割り当てできない」という問題が発生しましたが、サンプル モデルに「patient_attributes」があるため、これは機能しないのでしょうか?

これを解決したら、コミットする前に患者が存在するかどうかを最初に確認し、患者の名前でSAYTを実行しようとします...しかし、それは将来のステップです!

ご協力いただきありがとうございます

El-Keyのアドバイスと提案に従った後、解決策を見つけました

更新、最終コード - 私の解決策

models/samples.rb

class Sample < ActiveRecord::Base
  attr_accessible :approved, :patient_id, :result, :patient_attributes

  belongs_to :patient
  accepts_nested_attributes_for :patient
end

models/patient.rb

class Patient < ActiveRecord::Base
  attr_accessible :date_of_birth, :patient_name 
  has_many :samples
end

コントローラー/samples_controller

def new
    @sample = Sample.new
    @sample.build_patient

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @sample }
    end
end

def create
    @sample = Sample.new(params[:sample])

    respond_to do |format|
      if @sample.save
        format.html { redirect_to @sample, notice: 'Sample was successfully created.' }
        format.json { render json: @sample, status: :created, location: @sample }
      else
        format.html { render action: "new" }
        format.json { render json: @sample.errors, status: :unprocessable_entity }
      end
    end
end

ビュー/サンプル/_form.html.erb

<%= form_for(@sample) do |f| %>
  <% if @sample.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@sample.errors.count, "error") %> prohibited this sample from being saved:</h2>

      <ul>
      <% @sample.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :result %><br />
    <%= f.text_area :result %>
  </div>
    <div class="field">
        <%= f.label :patient_id, 'Patient ID' %><br />
        <%= f.text_area :patient_id %>
    </div>
  <div class="field">
    <%= f.label :approved %><br />
    <%= f.check_box :approved %>
  </div>

  <div><%= render 'patient', f: f %></div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

ビュー/サンプル/_patient.html.erb

<%= f.fields_for :patient do |p| %>
<div class="field">
       <%= p.label :patient_name %><br />
       <%= p.text_field :patient_name %>
</div>
<div class="field">
       <%= p.label :date_of_birth %><br />
       <%= p.date_select :date_of_birth %>
</div>
<% end %>
4

2 に答える 2

2
  1. サンプル テーブルの外部キーではなく、別のフィールドである患者 ID がある場合は、:patient_id を介して使用できるようにするか、患者 ID が別の目的で使用される場合はそのままにしておく必要があります。

  2. のフィールドに新しいオブジェクトを与える必要があります

サンプルモデルを次のように変更します

attr_accessible :approved, :patientID, :result, :patient_attributes

とからのサンプルフォーム行

<div><%= render 'patient', f: f %></div>

<div>
<%= f.fields_for :patient, Patient.new do |p| %>
  <%= p.text_field :name %>
  <%= p.text_field :date_of_birth %>
<% end %>
</div>

仕組みを理解するためのサンプル アプリを作成しました。

https://github.com/ravensnowbird/inverse_nested

@sample.build_patient も削除できます。

于 2013-10-17T10:18:29.157 に答える
2

メソッドは、次のfields_forような親フォームから呼び出す必要があります。

_form.html.erb

<div><%= render 'patient', f: f %></div>

患者.html.erb

<%= f.fields_for :patient do |p| %>
  <!-- code -->
<% end %>

これを試して。それでもうまくいかない場合は、コントローラーを見せていただけますか。この助けを願っています

編集
[ Ok] 次に、サンプル モデルをpatient次のように置き換えてみてくださいpatient_attributes

attr_accessible patient_attributes: [:patient_name, :date_of_birth]
于 2013-10-14T21:28:08.947 に答える