2012-04-27 50 views
4

我在公司模型的序列化列:如何编辑表单textarea的序列化的哈希列

class Company < ActiveRecord::Base 
    serialize :names 

理想我希望它在数据库中像这样不同的名称保存:

--- 
short: bestbuy 
long: bestbuy ltd. 

目前在我公司#编辑页面,我有这方面的文本区域:

<%= f.text_area :names %> 

如果我有YAML在数据库中,该宏将会L为显示在浏览器为:当我提交

{"short"=>"bestbuy", "long"=>"bestbuy ltd."} 

然而,在数据库中它变成了:

--- ! '{"short"=>"bestbuy", "long"=>"bestbuy ltd."}' 

问题

我怎样才能让这个textarea显示YAML供编辑编辑?

如何让数据库保存正确的YAML,而不是YAML和红宝石哈希的混搭?

更新

如果我强迫列是Hash类型是这样的:

serialize :names, Hash 

它会给错误,当我试图保存:

ActiveRecord的: :Admin :: CompaniesController中的SerializationTypeMismatch#update
属性was应该是一个哈希,但一个String

+1

我很想知道这个答案。 – pixelearth 2012-04-27 05:41:42

回答

0

逾期回答我自己的问题:

class ConfigSerializer 
    def self.load(i) 
    if i.blank? 
     {} 
    else 
     YAML.load(i) 
    end 
    end 

    def self.dump(i) 
    i = {} if i.blank? 

    if i.is_a?(String) # Allow assigning an YAML string as input 
     i 
    else 
     YAML.dump(i) 
    end 
    end 
end 

,并在模型

serialize :names, ConfigSerializer 

这样我可以分配一个YAML字符串,它会被存储到数据库中的。只有当它从数据库加载它被转换为散列对象。

在视图中,我将textarea设置为具有原始YAML字符串,因此用户可以对其进行编辑。

-2

尝试的名字存储到数据库一样:

names = HashWithIndifferentAccess.new({"short"=>"bestbuy", "long"=>"bestbuy ltd."}) 
company = Company.new 
company.names = names.to_yaml 

希望,它将帮助。

+1

这是行不通的,你只会以YAMLed YAML结束,这对任何人都没有帮助。 – 2012-04-27 06:33:19

4

您可以使用原始SQL手工编写数据库,但如果您不知道自己在做什么,我不会推荐它。一个必然结果是,除非你已经知道你正在做什么,否则你不应该混淆数据库的YAML版本。

取而代之的是,将数据转换到YAML自己:

@names = m.names.to_yaml 

,然后东西@names到您<textarea>。然后保存编辑YAML,解析回一个Hash和它交给你的模型:

m.names = YAML.parse(params[:names]) 

# Or modify `params` in-place 
params[:name] = YAML.load(params[:names]) 
# then stuff `params` into `m` as usual 

是有点安全,你应该指定你的names应该在模型中的哈希:

serialize :names, Hash 

我不是serialize的粉丝,所以我通常建议不要使用它;但是,如果要使用它,则应始终指定class_name以使其更安全。


您当前的做法是把to_s版本的散列进入<textarea>

{"short"=>"bestbuy", "long"=>"bestbuy ltd."} 

这是一个字符串,而不是一个散列;它可能看起来像一个哈希,但HTML不知道Ruby哈希是什么,所以它只是一个字符串。然后你读的那句话,放入names然后YAMLifies(字符串),以这样的:

--- ! '{"short"=>"bestbuy", "long"=>"bestbuy ltd."}' 

这是在YAML,这看起来很像一个哈希,但字符串仍然字符串的字符串。

+0

谢谢。我认为它应该是'YAML.load'而不是'YAML.parse'。我必须在更新操作中执行以下操作:'@company.names = YAML.load(params [:company] [:names]); PARAMS [:公司] .delete(:名称)'。这很麻烦,所需的工作似乎超过了方便。我在这里错过了什么? – lulalala 2012-04-27 07:42:42

+0

@lulalala:你说'YAML.load'是对的,那是我的手指没有做我的大脑告诉他们的。是的,这是一个很大的麻烦,但是你试图颠覆'serialize',所以不应该让人感到意外。无论如何,你为什么要这么做? – 2012-04-27 07:56:03

+0

谢谢。我试图为名称中的每个名称创建动态表单域。然而,由于名称类型无法预先确定,因此很困难。最后,我认为让他们编辑一个textarea可能是最容易做到的。 – lulalala 2012-04-27 08:01:34