Ruby on rails 如何在rails中构建一个复杂的表单,允许我关联或创建一个新的相关实体?

Ruby on rails 如何在rails中构建一个复杂的表单,允许我关联或创建一个新的相关实体?,ruby-on-rails,forms,Ruby On Rails,Forms,关于rails复杂表单的stackoverflow有很多问题,它们似乎都指向Ryan Bates关于这个主题的railscast演示:和 这很好,但我看不出有什么问题可以解决您可能想要创建新的子对象,或者您可能想要关联已经存在的对象的情况 在我的例子中,我希望用户能够创建一个新的事件。作为其中的一部分,他们需要说明谁参与了这起事件。大约有一半的时间,被添加到事件中的人员已经存在于db中。在这种情况下,应该鼓励用户使用这些现有记录,而不是创建新记录 对于如何在表单中处理这种复杂性,有什么建议吗 作

关于rails复杂表单的stackoverflow有很多问题,它们似乎都指向Ryan Bates关于这个主题的railscast演示:和

这很好,但我看不出有什么问题可以解决您可能想要创建新的子对象,或者您可能想要关联已经存在的对象的情况

在我的例子中,我希望用户能够创建一个新的事件。作为其中的一部分,他们需要说明谁参与了这起事件。大约有一半的时间,被添加到事件中的人员已经存在于db中。在这种情况下,应该鼓励用户使用这些现有记录,而不是创建新记录

对于如何在表单中处理这种复杂性,有什么建议吗


作为解决方案的一部分,您是否建议,如果用户找不到用户,则应用程序会在提交父对象之前进行动态创建?我的想法(但对听取建议感兴趣)是用户应该使用现有的人员记录(如果有),但如果用户需要创建新的人员记录,则在用户提交事件之前,该新记录不会提交给DB。想法?

嗨,要完成你需要做的事情,有几个简单的步骤可以遵循: 1) 在模型类(案例中的事件和人员类)中,请确保放置以下内容:

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
就这样,如果你需要进一步的帮助,请告诉我。
联邦快递

嗨,联邦快递,谢谢你的帮助。我不确定我是否理解正确。此代码是否允许用户为事件选择现有人员?如果是这样的话,我就不明白了。那是哪里?我的坏雪人,我完全忘了你需要那个呵呵!请看一看,我更新了我的答案与所有你需要的!我需要学习一点,但看起来正是我想要的。谢谢你的帮助!别担心!请允许我给你最后一个提示,我建议你看一下,它将使你在RoR中处理表单时的生活更加轻松。
# 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 %>
# 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