Rails 5.1.4 - 如何使用has_many:through关系从多选中创建记录?

时间:2017-11-06 16:43:06

标签: ruby-on-rails multi-select has-many-through

我在保存has_many :through关联的记录方面遇到了一些问题。我一定错过了重要的事情。

首先要做的事情:

  • Rails版本:5.1.4
  • Ruby版本:2.4.2

我有三个模型:

class Event < ApplicationRecord
  has_many :events_timeslots
  has_many :timeslots, through: :events_timeslots
end

class Timeslot < ApplicationRecord
  has_many :events_timeslots
  has_many :events, through: :events_timeslots
end

class EventsTimeslot < ApplicationRecord
  belongs_to :event
  belongs_to :timeslot
end

据此,每个事件都有很多时段,每个时段都有很多事件。

我想在我的视图中进行多重选择:

<%= form_with(model: event, local: true) do |form| %>
  ...
  <% fields_for :events_timeslots do |events_timeslots| %>
    <%= events_timeslots.label :timeslots %>
    <%= events_timeslots.select(:timeslots, @timeslots.collect {|t| [t.name, t.id]}, {}, {multiple: true}) %>
  <% end %>
  ...
<% end %>

这是在创建新事件时选择多个时隙的正确方法吗?时隙已经存在,但是当事件被保存时,它还应该在events_timeslots表中创建关联的记录。

我还允许强参数中的timeslots属性:

params.require(:event).permit(:date, timeslots: [])

是否有神奇的Rails-Way使用“scaffolded”控制器操作来创建新事件以及EventsTimeslot模型中的相关记录?与此问题相关,我发现an answer on another question,但我无法让它工作!

也许我错过了一个非常愚蠢的小事,但无论如何感谢你的帮助。

修改

events_timeslots中的{混乱)schema.rb表:

create_table "events_timeslots", force: :cascade do |t|
  t.bigint "events_id"
  t.bigint "timeslots_id"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
  t.index ["events_id"], name: "index_events_timeslots_on_events_id"
  t.index ["timeslots_id"], name: "index_events_timeslots_on_timeslots_id"   
end

3 个答案:

答案 0 :(得分:3)

假设您的外键是标准:event_idtimeslot_id ...

然后尝试在timeslots方法中使用timeslot_ids替换permit

params.require(:event).permit(:date, timeslot_ids: [])

然后,不要以嵌套的形式设置连接表的属性,只需更新timeslot_ids上的@event

<%= form_with(model: event, local: true) do |form| %>

    <%= form.select(:timeslot_ids, Timeslot.all.collect {|t| [t.name, t.id]}, {}, {multiple: true}) %>

<% end %>

答案 1 :(得分:1)

fields_for适用于使用accepts_nested_attributes创建嵌套记录时。

当您只是关联项目时不需要它:

<%= form_with(model: event, local: true) do |form| %>
  <%= f.collection_select(:timeslot_ids, Timeslot.all, :id, :name, multiple: true) %>
<% end %>

ActiveRecord为has_many关联创建一个_ids setter方法,该方法接受一组id。这与form helpers一起使用。

要将数组参数列入白名单,您需要将其作为关键字传递给允许:

params.require(:event).permit(:foo, :bar, timeslot_ids: [])

使用[]允许任何标量值。

答案 2 :(得分:0)

我认为您正在寻找“自动保存”,请点击此处http://api.rubyonrails.org/classes/ActiveRecord/AutosaveAssociation.html