1

Railsの複雑なフォームに関するstackoverflowには多くの質問があり、それらはすべて、このテーマに関するRyan Batesの素晴らしいrailscastデモ(part1とpart2)を指し示しているようです。

これは、それが行うことには最適ですが、新しい子オブジェクトを作成したい場合や、既存のオブジェクトを関連付けたい場合の状況に対処する質問はありません。

私の場合、ユーザーが新しいインシデントを作成できるようにしたいと思います。その一環として、彼らは誰が事件に関与したかを言う必要があります。約半分の時間、インシデントに追加されている人はすでにデータベースに存在しています。その場合、ユーザーは、新しいレコードを作成するのではなく、それらの既存のレコードを使用するように奨励されるべきです。

フォームでこの複雑さを処理する方法に関する提案はありますか?

そして、解決策の一部として、親オブジェクトが送信される前に、ユーザーがアプリの先に進んでいる人を見つけられず、その場で作成することをお勧めしますか?私の考えでは(ただし、推奨事項を聞くことに興味があります)、ユーザーは既存のPersonレコードがある場合はそれを使用する必要がありますが、ユーザーが新しいPersonレコードを作成する必要がある場合、この新しいレコードはDBに送信されません。ユーザーがインシデントを送信します。考え?

4

1 に答える 1

2

こんにちは、あなたがする必要があることを達成するために、従うべきいくつかの簡単なステップがあります:1)モデルクラス(あなたの場合はIncidentクラスとPersonクラス)に次のようなものを入れてください:

class Incident < ActiveRecord::Base
    has_and_belongs_to_many :people
    # Note if you want to be able to remove a person from the Incident form (to de-associate) put true in :allow_destroy => true on the accepts_nested_attributes_for
    accepts_nested_attributes_for :people, :allow_destroy => false, :reject_if => :all_blank
    validates_associated :people #so you won't be able to save invalid people objects
    attr_accessible :date_occur, :location, :people_attributes # note the :people_attributes here
    #do your Incident validations as usual...        
end

class Person < ActiveRecord::Base
    has_and_belongs_to_many :incidents
    #the following line it's to allow mass assignment, basically it will allow you to create people from the Incident form
    attr_accessible :first_name, :last_name, :dob 
    #do your Person validations as usual...
end

2)ビュー側では、インシデントフォームファイル(app / view / Incidents / _form.html.erb)を変更して、ユーザーが既存のユーザーを割り当て、新しいユーザーをインシデントに作成できるようにするのが最も簡単な方法です。

# app/view/incidents/_form.html.erb

<%= semantic_form_for(@incident) do |f| %>
    <% if @incident.errors.any? %>
    <div id="error_explanation">
        <h2><%= pluralize(@incident.errors.count, "error") %> prohibited this incident from being saved:</h2>
        <ul>
            <% @incident.errors.full_messages.each do |msg| %>
                <li><%= msg %></li>
            <% end %>
        </ul>
    </div>
    <% end %>

    <div class="field">
        <%= f.label :date_occur %><br />
        <%= f.datetime_select :date_occur %>
    </div>
    <div class="field">
        <%= f.label :location %><br />
        <%= f.text_field :location %>
    </div>

    <%= f.input :people, :as => :select, :collection=>Hash[Person.all.map { |p| [p.first_name + ' - ' + p.last_name, p.id] }] %>

    <%= f.fields_for :people, Person.new() do |new_person_form| %>
        <div class="incident-people new-person">
            <%= new_person_form.inputs    :name=>'Add New person' do %>
                <%= new_person_form.input :first_name, :label=>'First Name: ' %>
                <%= new_person_form.input :last_name, :label=>'Last Name: ' %>
                <%= new_person_form.input :dob, :label=>'Date of birth: ' %>
            <% end %>
        </div>
    <% end %>


  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

3)最後に、次のように、更新を変更し、インシデントコントローラーのメソッドを作成する必要があります。

# app/controllers/incident_controller.rb
def create
    selected_people = params[:incident][:person_ids].keep_if{ |v| v.present? }
    params[:incident].delete(:person_ids)
    @incident = Incident.new(params[:incident])
    @incident.people = Person.find( selected_people )

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

def update
    selected_people = params[:incident][:person_ids].keep_if{ |v| v.present? }
    params[:incident].delete(:person_ids)
    @incident = Incident.find(params[:id])
    @incident.people = Person.find( selected_people )
    respond_to do |format|
        if @incident.update_attributes(params[:incident])
            format.html { redirect_to @incident, notice: 'Incident was successfully updated.' }
            format.json { head :no_content }
        else
            format.html { render action: "edit" }
            format.json { render json: @incident.errors, status: :unprocessable_entity }
        end
    end
end

それだけです。さらにサポートが必要な場合はお知らせください。FedeX

于 2012-07-10T23:11:41.417 に答える