编辑序列化模型的表格

时间:2013-12-10 10:42:52

标签: ruby-on-rails forms serialization ruby-on-rails-4 simple-form

我有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

我无法了解如何使用单个字段为数组中的每个元素创建正确的编辑表单。 将不胜感激任何帮助。

1 个答案:

答案 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方法。让我稍微测试一下,并改进这个想法。