0

我有一个Sezzion模型:

attr_accessible  :description
has_many :session_instructors, :dependent => :destroy
has_many :instructors, :through => :session_instructors
accepts_nested_attributes_for :session_instructors
accepts_nested_attributes_for :instructors

Instructor模型:

attr_accessible :bio
has_many :sezzions, :through => :session_instructors
has_many :session_instructors, :dependent => :destroy

SessionInstructor模型:

attr_accessible :instructor_id, :sezzion_id
belongs_to :sezzion
belongs_to :instructor

最后,User型号:

has_many :sezzions
has_many :instructors

我正在尝试为Sezzion嵌套表单创建一个表单,SessionInstructor该表单具有多个选择选项Instructors

我该如何执行以下操作:

  1. 嵌套形式SessionInstructor
  2. 使用多项选择选项来获取所有选定Instructorinstructor_id
  3. 隐藏字段以传递session_id每个选择的讲师创建/更新的内容

到目前为止,我有以下代码:

<%= form_for(@sezzion) do |f| %>

    <%= f.label :description %>
    <%= f.text_area :description %>


    <%= f.label :instructors %>
    <%= fields_for :session_instructors do |f| %>
      <select multiple>
        <% current_user.instructors.each do |instructor| %>
          <option><%= instructor.name %></option>
        <% end %>
      </select>
    <% end %>

    <%= f.submit %>

<% end %>

非常感谢!

4

3 回答 3

4

这在 Rails 中似乎很难做到。

我认为这样的事情可能会奏效:

<%= f.fields_for :session_instructors do |si| %>
  <%= si.collection_select :instructor_ids, current_user.instructors, :id, :name, multiple: true>
<% end %>

这应该创建一个表单元素,它将设置 sezzion[session_instructors_attributes][instructor_ids]。

虽然我不确定这是否真的是你想要的。我从来没有尝试过使用多选。如果它不起作用,您也可以尝试摆脱fields_for并仅使用f.collection_select. 如果您愿意使用复选框,我可以肯定地向您展示如何做到这一点。

我希望这会有所帮助。

编辑:

以下是我通常使用 a 的方式check_box

<%= f.fields_for :session_instructors do |si| %>
  <%= si.hidden_field "instructor_ids[]" %>
  <% current_user.instructors.each do |i| %>
    <%= si.check_box "instructor_ids[]", i.id, i.sezzions.include?(@sezzion), id: "instructor_ids_#{i.id}" %>
    <%= label_tag "instructor_ids_#{i.id}", i.name %>
  <% end %>
<% end%>

有几个“陷阱!” 用这种方法。编辑模型时,如果取消选中所有复选框,则根本不会发送参数。这就是为什么hidden_field是必要的。此外,您需要确保每个表单元素都有一个唯一的id字段。否则只发送最后一个条目。这就是我自己手动设置值的原因。

我复制粘贴然后编辑。希望我的语法足够接近,你可以让它工作。

最终编辑:

根据 Sayanee 在下面的评论,答案比我想象的要简单一些:

<%= f.collection_select :instructor_ids, current_user.instructors, :id, :name, {}, {:multiple => true} %>
于 2013-01-29T19:00:28.420 回答
0

@Sayanee,您能发布一下您的讲师、sezzions 表的样子吗?另请注意,您无法从 Instructor 对象获取instructor_ids,因此您会收到“未定义的方法”错误。使用您共享的当前关联,您可以从 Sezzion 对象获取instructor_ids。所以你需要遍历 current_user.sezzions 而不是 current_user.instructors。

于 2013-02-18T13:02:07.103 回答
0

这是一种在 has_many :through 关联的情况下使用 html multiple_select 实现 fields_for 嵌套表单的方法。通过做这样的事情来解决它。表单视图:

<%= form_for(@sezzion) do |f| %>
...

    <%= fields_for :session_instructors do |g| %>
        <%= g.label :instructor, "Instructees List (Ctrl+Click to select multiple)" %>:
        <%= g.select(:instructor_id, Instructor.all.collect { |m| [m.name, m.id] }, {}, { :multiple => true, :size => 5 }) %>
        <%= g.hidden_field :your_chosen_variable_id, value: your_chosen.id %>
    <% end %>
...
<%= f.submit %>

<% end %>

注意:由于在生成表单时不会保存 @sezzion,因此您无法通过该表单传递该 id (@sezzion.id) 来代替 your_chosen.id。您可以在控制器中处理该保存。

确保您的控制器在生成表单时初始化变量:您的 def new 可能如下所示:

def new
  @sezzion = Sezzion.new
  @sezzion.session_instructor.build
  @sezzion.instructors.build
end

现在创建控制器必须能够接受多选所需的强参数,所以 sezzion_params 方法可能看起来像这样:

def sezzion_params
    params.require(:sezzion).permit(:description, :any_other_fields,
                                 :session_instructors_attributes  => 
                                     [:instructor_id => [], :your_chosen_id => Integer])
end

在 create 函数中,第一个 session_instructor 变量通过我们的新函数链接到 @sezzion 实例变量。如果您想将创建的@sezzion.id 传递给每个选择讲师,则必须在保存 Sezzion 实例后构建我们的多选中的其他 session_instructors。.

def create
    @sezzion = Sezzion.new(sezzion_params)
    @startcount=1 #The first element of the array passed back from the form with multiple select is blank
    @sezzion.session_instructors.each do |m|
      m.instructor_id = sezzion_params["session_instructors_attributes"]["0"]["instructor_id"][@startcount]
      m.your_chosen_variable_id = your_chosen.id
      @startcount +=1
    end

    if @sezzion.save
        sezzion_params["session_instructors_attributes"]["0"]["instructor_id"].drop(@startcount).each do |m|
        @sezzion.session_instructors.build(:instructor_id => sezzion_params["session_instructors_attributes"]["0"]["instructor_id"][@startcount],
                                 :your_chosen_variable_id => your_chosen.id).save
        @startcount += 1
      end
      flash[:success] = "Sezzion created!"
      redirect_to root_url
    else
      flash[:danger] = "There were errors in your submission"
      redirect_to new_sezzion_path
    end
end
于 2015-12-29T08:20:18.543 回答