使用 Rails 序列化将哈希保存到数据库

Posted

技术标签:

【中文标题】使用 Rails 序列化将哈希保存到数据库【英文标题】:Using Rails serialize to save hash to database 【发布时间】:2011-10-05 09:13:31 【问题描述】:

我正在尝试将哈希映射 ID 保存到我的 rails 应用程序中的多次尝试中。我迁移到数据库以容纳这个新列:

class AddMultiWrongToUser < ActiveRecord::Migration
  def self.up
    add_column :users, :multi_wrong, :string
  end

  def self.down
    remove_column :users, :multi_wrong
  end
end

在我的模型中,我有:

class User < ActiveRecord::Base 
 serialize :multi_wrong, Hash
end

但是当我使用 rails 控制台来测试这个时:

user = User.create()
user.multi_wrong = "test"=>"123"
user.save

输出为假。这里出了什么问题?

【问题讨论】:

尝试保存记录后user.errors中是否有任何内容? 以后可以使用bang方法(save!)引发异常并显示错误信息。 最佳答案现在使用 JSON 列 ***.com/a/21397522/1536309 【参考方案1】:

列类型错误。您应该使用文本而不是字符串。因此,您的迁移应该是:

 def self.up
   add_column :users, :multi_wrong, :text
 end

Rails 会为您正确地将其转换为 YAML(并执行正确的序列化)。字符串字段的大小有限,只能保存特别小的值。

【讨论】:

@BenjaminTan 背后的原因是什么,为什么我不能将哈希存储在“字符串”数据类型中。 因为在数据库中,String的长度固定为255(我认为)。但是如果你要序列化一个比较大小的哈希,这很容易超过长度。数组的情况相同。文本允许更大的长度。【参考方案2】:

更新:

具体实现将取决于您的数据库,但 PostgreSQL 现在有 jsonjsonb 列,它们可以本地存储您的哈希/对象数据并允许您 query against the JSON with ActiveRecord!

更改您的迁移,您就完成了。

class Migration0001
  def change
    add_column :users, :location_data, :json, default: 
  end
end

原文:

更多详情:rails docs && apidock

确保您的专栏是 :text 而不是 :string

迁移:

$ rails g migration add_location_data_to_users location_data:text

应该创建:

class Migration0001
  def change
    add_column :users, :location_data, :text
  end
end

你的班级应该是这样的:

class User < ActiveRecord::Base
  serialize :location_data
end

可用操作:

b = User.new
b.location_data = [1,2,foot: 3, bart: "noodles"]
b.save

更棒?!

利用 postgresql hstore

class AddHstore < ActiveRecord::Migration  
  def up
    enable_extension :hstore
  end

  def down
    disable_extension :hstore
  end
end 

class Migration0001
  def change
    add_column :users, :location_data, :hstore
  end
end

使用 hstore,您可以在序列化字段上设置属性

class User < ActiveRecord::Base  
  # setup hstore
  store_accessor :location_data, :city, :state
end

【讨论】:

真的很棒!谢谢!【参考方案3】:

Rails 4 有一个名为Store 的新功能,因此您可以轻松地使用它来解决您的问题。您可以为它定义一个访问器,建议您将用于序列化存储的数据库列声明为文本,因此有足够的空间。原始示例:

class User < ActiveRecord::Base
  store :settings, accessors: [ :color, :homepage ], coder: JSON
end

u = User.new(color: 'black', homepage: '37signals.com')
u.color                          # Accessor stored attribute
u.settings[:country] = 'Denmark' # Any attribute, even if not specified with an accessor

# There is no difference between strings and symbols for accessing custom attributes
u.settings[:country]  # => 'Denmark'
u.settings['country'] # => 'Denmark'

【讨论】:

以上是关于使用 Rails 序列化将哈希保存到数据库的主要内容,如果未能解决你的问题,请参考以下文章

使用 Ruby on Rails 从数据库中的 yaml 序列化字段中获取大小数

Ruby On Rails 中的编组与 ActiveRecord 序列化

ruby 将Ruby对象转换为哈希。这不是用于对象序列化或映射,而是用于保存包含的信息

Rails 中字段的自定义序列化

Rails 3 应用程序/用户设置最佳实践?

哈希被保存到数据库但无法在 Rails 表单中呈现其值?