在模型Code
中,有一个名为week_days
的字段可能类似于此1100110
。
我希望在ActiveAdmin表单中显示7个复选框,而不是经典输入字段,如此
form do |f|
f.inputs do
f.input :name
f.input :week_days
end
f.actions
end
所以我想在模型中写一个这样的映射器
def week_days_checkboxes
[
['sunday', 1],
['monday', 1],
['tuesday', 1],
['wednesday', 1],
['thursday', 1],
['friday', 1],
['saturday', 1]
]
end
def week_days_checkboxes=(week_days_checkboxes)
@week_days = week_days_checkboxes.reverse.join.to_i(2)
end
然后以这种方式更改表单输入
f.input :week_days_checkboxes, as: :check_boxes
但它不起作用。我该怎么办?
PS:根据字段week_days
非常感谢
答案 0 :(得分:5)
由于以下几个原因,它不起作用:
self[:column_name]= value
或write_attribute(:column_name, value)
(我认为后者更有意图揭示)。要阅读,您可以使用self[:column_name]
或read_attribute
方法。['', '1']
。在这种情况下,基本上不使用统一值。从week_days_checkboxes
方法返回数组数组将不会显示选项列表,因为它表示值而不是选项。您必须明确设置集合。
f.input :week_days, as: :check_boxes, collection: week_days_for_select
week_days_for_select
返回适当的列表。
当您编辑现有模型时,不会在复选框列表中选择之前选择的日期。为此,您需要返回与复选框输入相匹配的值列表。值。
一种解决方案可能是:
在您看来:
f.input :week_days, as: :check_boxes, collection: Date::DAYNAMES
然后在你的模型中为week_days
创建一个包装器,使它接受一个列表并将其转换为整数,反之亦然。
def week_days
return [] if read_attribute(:week_days).blank?
# first you have to convert the integer to a binary array
w = read_attribute(:week_days)
days_as_binary = Math.log2(w).floor.downto(0).map { |nth_bit| w[nth_bit] }
# alternatively
# days_as_binary = read_attribute(:week_days).to_s(2).split('').map(&:to_i)
# make sure it has an element for every day of the week
padded_binary = [0] * (7 - days_as_binary.size) + days_as_binary
# map the binary array to day names
padded_binary.each_with_index.map do |d, idx|
Date::DAYNAMES[idx] if d == 1
end.compact
end
def week_days=(values)
days = Date::DAYNAMES.map { |d| values.include?(d) ? 1 : 0 }
write_attribute(:week_days, days.join.to_i(2))
end
虽然我认为将所选天数表示为整数并不是您的最佳选择。如果您使用的是PostgreSQL,AR 4+可以很好地支持数组 - 您可以将数据列表保存到数据库中。