Using Rails serialize to save hash to database
Solution 1
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.
Solution 2
UPDATED:
Exact implementation will depend on your database, but PostgreSQL now has json
and jsonb
columns which can natively store your hash/object data and allow you to query against the JSON with ActiveRecord!
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
Make sure your column is :text
and not :string
Migration:
$ 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
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
class User < ActiveRecord::Base
# setup hstore
store_accessor :location_data, :city, :state
end
Solution 3
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:
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'
cmwright
Updated on April 16, 2020Comments
-
cmwright about 4 years
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:
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:
user = User.create() user.multi_wrong = {"test"=>"123"} user.save
The output is false. What's going wrong here?
-
Lohith MV about 12 years@BenjaminTan what is the reason behind it,why does I can't store hash in 'string' data type.
-
Benjamin Tan Wei Hao about 12 yearsBecause in the database, String has a fixed length of 255 (I think). But if you were to serialize a hash of comparative size, this would easily exceed the length. Same case for Arrays. Text allows for much bigger lengths.
-
Alexander Gorg almost 7 yearsTruly awesome! Thanks!