在您的模型中,您可以从序列化哈希或数组的键中动态分配属性。我已经做了类似的事情,所以我正在修改我的代码以获取下面的几个示例。基本上,通过动态创建虚拟属性,使用像 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_0 到 self.exhibition_9,但它也排除了任何 setter 方法,因为它不匹配 self.exhibition_0=
f.object.methods.grep(/^exhibition_.*?(?<!=)$/).each do |method_name|
f.input method_name
end
我还没有完全测试过这个经过修改的代码,但其中大部分是在我自己的几个类中工作的。此外,可能还需要动态创建 setter 方法。让我测试一下,然后改进这个想法。