Ruby-on-rails 使用 Rails 序列化将哈希保存到数据库

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6694432/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 01:35:42  来源:igfitidea点击:

Using Rails serialize to save hash to database

ruby-on-railsrubyserializationactiverecord

提问by cmwright

I'm try to save a hash mapping ids to a number of attempts in my rails app. My migration to the database to accommodate this new column:

我正在尝试将哈希映射 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

In my model I have:

在我的模型中,我有:

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

But when I use the rails console to test this by doing:

但是当我使用 rails 控制台通过执行以下操作来测试时:

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

The output is false. What's going wrong here?

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

回答by Benjamin Tan Wei Hao

The column type is wrong. You should use Text instead of String. Therefore, your migration should be:

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

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

Then Rails will properly convert it into YAML for you (and perform proper serialization). Strings fields are limited in size and will only hold especially-small values.

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

回答by Blair Anderson

UPDATED:

更新:

Exact implementation will depend on your database, but PostgreSQL now has jsonand jsonbcolumns which can natively store your hash/object data and allow you to query against the JSON with ActiveRecord!

确切的实现将取决于您的数据库,但 PostgreSQL 现在具有jsonjsonb列,可以本机存储您的哈希/对象数据,并允许您使用 ActiveRecord 查询 JSON

change your migration and you're done.

改变你的迁移,你就完成了。

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

ORIGINAL:

原来的:

For more details: rails docs&& apidock

有关更多详细信息:rails docs&& apidock

Make sure your column is :textand not :string

确保您的列是:text而不是:string

Migration:

移民:

$ rails g migration add_location_data_to_users location_data:text

$ rails g migration add_location_data_to_users location_data:text

should create:

应该创建:

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

Your Class Would Look Like:

你的班级看起来像:

class User < ActiveRecord::Base
  serialize :location_data
end

Available Actions:

可用操作:

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

More Awesome?!

更厉害?!

utilize postgresql hstore

使用 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

With hstore you can set attributes on the serialized field

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

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

回答by Aboozar Rajabi

Rails 4 has a new feature called Store, so you can easily use it to solve your problem. You can define an accessor for it and it is recommended you declare the database column used for the serialized store as a text, so there's plenty of room. The original example:

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'