Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 将Rails表单帮助程序与序列化的自定义类一起使用_Ruby On Rails_Ruby_Serialization_Activerecord_Ruby On Rails 3 - Fatal编程技术网

Ruby on rails 将Rails表单帮助程序与序列化的自定义类一起使用

Ruby on rails 将Rails表单帮助程序与序列化的自定义类一起使用,ruby-on-rails,ruby,serialization,activerecord,ruby-on-rails-3,Ruby On Rails,Ruby,Serialization,Activerecord,Ruby On Rails 3,我试图在一个DB字段中保存选项的散列。表单能够将数据保存到数据库中,但在我去编辑它时无法再次检索它(例如,除wp_选项字段外,所有其他字段都已预填充) 以我的名义: <%= form_for(@profile, :remote => true) do |f| %> ... <%= f.fields_for :wp_options do |wp_options| %> <%= wp_options.text_field :wp_name %

我试图在一个DB字段中保存选项的散列。表单能够将数据保存到数据库中,但在我去编辑它时无法再次检索它(例如,除wp_选项字段外,所有其他字段都已预填充)

以我的名义:

<%= form_for(@profile, :remote => true) do |f| %>
 ...
   <%= f.fields_for :wp_options do |wp_options| %>
      <%= wp_options.text_field :wp_name  %>
   <% end %>
 ...
在我的数据库列“wp_选项”中:

--- !map:ActiveSupport::HashWithIndifferentAccess 
wp_name: Test  

任何建议都将不胜感激。

事实上这很容易。您需要将类与
reader
方法一起使用。您可以使用不同的方法创建它,但最简单的方法是使用
OpenStruct
类(注意,它将无法看到OpenStruct实例方法中的字段……此类无法重新定义方法)

在表格中,您应添加:

<%= f.fields_for :wp_options, @profile.wp_options do |wp_options| %>
在这种情况下,只有当序列化的wp_选项是散列类时,它才会起作用

希望有帮助

另外,我使用了同样的技术,但因为我有
type
hash键,OpenStruct无法创建它,所以我使用了简单的Struct类。我有
数据
栏:

def data
  keys = current_data.keys
  data = attributes[:data]
  Struct.new(*keys).new(*keys.map { |k| data[k] })
end

稍微不那么琐碎,但无论如何都是相同的方法(在此之前我创建了特殊类,但现在我知道Struct是创建此类内容的更好方法。您可以在这里找到更多想法:)

对于使用Dmitry解决方案的用户,在rails 3.0.5上(不确定上一个/下一个版本,所以请尝试之前),添加

添加到environment.rb文件,以便包含OpenStruct

如果要使用JSON进行序列化,请在您的模型中添加(哦,我对RoR很陌生,所以请仔细研究并提出一个比这个更好的“有效”解决方案)(我的变量名更改为与上述示例匹配):


最后一点:老实说,我不知道为什么它必须存储在self.wp_选项中,而不是self.attributes['wp_选项'],如果有人能解释的话,那会很酷。

我遇到了同样的问题。我的解决办法如下:

  • 在助手中定义方法:

    def wp_options_text_field(profile, wp_options, name)
      wp_options.text_field name, :value => profile.wp_options[name]
    end
    
  • 在你看来:

    <%= form_for(@profile, :remote => true) do |f| %>
    ...
    <%= f.fields_for :wp_options do |wp_options| %>
      <%= wp_options_text_field :wp_name  %>
    <% end %>
    ...
    
    true)do | f |%>
    ...
    ...
    

  • 这里唯一的问题是,您需要为要使用的每个助手方法定义方法。在我的例子中,我只使用了两种方法,这并不痛苦。

    我需要我的wp_选项作为散列保留,这样我就可以迭代它的条目。因此,我没有对模型做任何更改,而是将
    OpenStruct.new
    以这样的形式放置:也许它的视图可以窥视模型实现,但它所知道的是wp_选项是一个散列,而不是一个带有attr方法的对象。
    def wp_options
      OpenStruct.new(self.attributes['wp_options'])
    end
    
    def data
      keys = current_data.keys
      data = attributes[:data]
      Struct.new(*keys).new(*keys.map { |k| data[k] })
    end
    
    require 'ostruct'
    
    before_save :json_serialize
    after_save  :json_deserialize
    after_find  :json_deserialize
    
    def json_serialize  
      self.wp_options = ActiveSupport::JSON.encode(self.attributes['wp_options'])
    end
    
    def json_deserialize
      unless (self.attributes['wp_options'].nil?)
        self.wp_options = ActiveSupport::JSON.decode(self.attributes['wp_options'].to_s)
      end
    end
    
    def wp_options_text_field(profile, wp_options, name)
      wp_options.text_field name, :value => profile.wp_options[name]
    end
    
    <%= form_for(@profile, :remote => true) do |f| %>
    ...
    <%= f.fields_for :wp_options do |wp_options| %>
      <%= wp_options_text_field :wp_name  %>
    <% end %>
    ...