我有Info.rb模型,用于保存所有展览和比赛的信息
class Info < ActiveRecord::Base
serialize :exhibition, Array
serialize :contest, Array
end
我希望能够编辑更新并向展览和比赛阵列添加新元素。这是我的 info_controller.rb
class Admin::InfoController < ApplicationController
before_action :find_info, only: [:edit, :update]
def index
@info = Info.all
end
def edit
end
def update
@info.update_attributes(info_params)
redirect_to admin_info_index_path
end
private
def find_info
@info = Info.first
end
def info_params
params.require(:info).permit({:contest => []}, {:exhibition => []})
end
end
我无法了解如何使用单个字段为数组中的每个元素创建正确的编辑表单。 将不胜感激任何帮助。
答案 0 :(得分:2)
在模型中,您可以从序列化哈希或数组的键中动态分配属性。我已经做了类似的事情,所以我在下面的几个例子中修改我的代码。基本上,通过动态创建虚拟属性,使用像Formtastic这样的DSL变得更加容易。
使用序列化数组:
class Info < ActiveRecord::Base
serialize :exhibition, Array
serialize :contest, Array
after_initialize :explode_exhibition
after_initialize :explode_contest
before_save :implode_exhibition
before_save :implode_contest
private
def explode_exhibition()
exhibition.each_with_index do |v,i|
self.class.send(:attr_accessor, "@exhibition_#{i}")
self.instance_variable_set("@exhibition_#{i}", v)
end
end
def explode_contest()
contest.each_with_index do |v,i|
self.class.send(:attr_accessor, "@contest_#{i}")
self.instance_variable_set("@contest_#{i}", v)
end
end
def implode_exhibition()
exhibition = []
self.methods.grep(/exhibition_/).each do |method_name|
exhibition << self.instance_variable_get("@#{method_name}", v)
end
end
def implode_contest()
contest = []
self.methods.grep(/contest_/).each do |method_name|
contest << self.instance_variable_get("@#{method_name}", v)
end
end
end
使用序列化哈希:
class Info < ActiveRecord::Base
serialize :exhibition, Hash
serialize :contest, Hash
after_initialize :explode_exhibition
after_initialize :explode_contest
before_save :implode_exhibition
before_save :implode_contest
private
def explode_exhibition()
exhibition.each do |k,v|
self.class.send(:attr_accessor, "@exhibition_#{k}")
self.instance_variable_set("@exhibition_#{k}", v)
end
end
def explode_contest()
contest.each do |k,v|
self.class.send(:attr_accessor, "@contest_#{k}")
self.instance_variable_set("@contest_#{k}", v)
end
end
def implode_exhibition()
exhibition.each do |k,v|
exhibition[k] = self.instance_variable_get("@exhibition_#{k}", v)
end
end
def implode_contest()
contest.each do |k,v|
contest[k] = self.instance_variable_get("@contest_#{k}", v)
end
end
end
然后在Formtastic中,您可以访问属性并为每个虚拟属性动态构建表单。注意正则表达式,可以使用一些迭代,因为它目前只会通过self.exhibition_9匹配self.exhibition_0,但它也通过不匹配self.exhibition_0 =
之类的方法排除任何setter方法 f.object.methods.grep(/^exhibition_.*?(?<!=)$/).each do |method_name|
f.input method_name
end
我还没有完全测试过这个带有密码的代码,但是我的大部分代码都是在我自己的几个代码中工作的。此外,可能还需要动态创建setter方法。让我稍微测试一下,并改进这个想法。