您正在使用form_for,因此f 是一个表单生成器。这意味着它绑定到您初始化它的对象,我们称之为@habit。由于您在表单构建器上调用collection_check_boxes,它会执行类似@habit.send(:commit) 的操作来咨询是否应该选中复选框,而目前(显然)不是。换句话说,如果你想使用 form_for ,你需要在模型本身中表示这个“一切都被检查”的事实。
现在我不确定您的模型层是什么样的,所以我将介绍一些场景。如果您有这样的has_and_belongs_to_many 关系:
class Habit < ActiveRecord::Base
has_and_belongs_to_many :committed_days
end
class CommittedDay < ActiveRecord::Base
has_and_belongs_to_many :habits
# let's assume it has the columns :id and :name
# also, let's assume the n:m table committed_days_habits exists
end
那么我认为最简单的方法是在控制器本身做这样的事情:
def new
@habit = Habit.new
@habit.committed_day_ids = CommittedDay.all.map(&:id)
end
在你的 ERB 中做:
<%= f.collection_check_boxes(:committed_day_ids, CommittedDay.all, :id, :name)
现在,使用 has-and-belongs-to-many 执行此操作可能有点过头了,尤其是在一周中的几天(这意味着 CommittedDay 表有 7 条记录,每天一条,这有点尴尬) .所以你也可以考虑简单地将一个星期数组序列化到数据库中,然后确保该列的默认值包含所有这些。
ERB 将与您写的类似:
<%= f.collection_check_boxes :committed, Date::ABBR_DAYNAMES, :downcase, :to_s %>
如果您使用 Postgres,您的课程可以很简单:
class Habit < ActiveRecord::Base
end
序列化代码将在迁移中:
# downcase is used since in the ERB you are using :downcase for the id method
t.text :committed, default: Date::ABBR_DAYNAMES.map(&:downcase), array: true
如果您不使用 Postgres,则可以使用与 DB 无关的 Rails 序列化:
class Habit < ActiveRecord::Base
serialize :committed, Array
end
然后您的迁移将如下所示:
t.text :committed, default: Date::ABBR_DAYNAMES.map(&:downcase).to_yaml