4

我在公司模型中有一个序列化列:

class Company < ActiveRecord::Base
  serialize :names

理想情况下,我希望它在数据库中存储这样的不同名称:

---
short: bestbuy
long: bestbuy ltd.

目前在我的公司#edit 页面中,我有一个文本区域:

<%= f.text_area :names %>

如果我在数据库中有该 YAML,它将在浏览器中显示为:

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

但是,当我提交它时,它在数据库中变成了:

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

问题

如何使 textarea 显示 YAML 以供编辑者编辑?

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

更新

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

serialize :names, Hash

当我尝试保存时会出错:

Admin::CompaniesController#update
属性中的 ActiveRecord::SerializationTypeMismatch 应该是 Hash,但实际上是 String

4

3 回答 3

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应该是模型中的 Hash:

serialize :names, Hash

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


您当前的方法是将to_s您的 Hash 版本放入<textarea>

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

那是一个字符串,而不是一个哈希;它可能看起来像一个哈希,但 HTML 不知道 Ruby 哈希是什么,所以它只是一个字符串。然后您将其读回并将其放入names其中,然后 YAML 将其(作为字符串)转换为:

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

那是 YAML 中的一个字符串,一个看起来很像 Hash 但实际上是一个字符串的字符串。

于 2012-04-27T06:32:48.427 回答
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 字符串,因此用户可以对其进行编辑。

于 2016-02-23T02:01:30.317 回答
-2

尝试将名称存储到数据库中,例如:

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

希望,它会有所帮助。

于 2012-04-27T05:59:38.497 回答