すべての出会いが美しいとは限らない。すべての別れが悲しいとは言えない。

0%

【Rails】使用serialize

ActiveRecord::Base serialize

Rails 中通过使用 serialize 直接将对象转化为字符串保存在数据库中。

1
2
3
class User < ActiveRecord::Base
serialize :group_ids
end

通过以上的方式,User#group_ids 被字符串化并保存,并不需要其他多余的处理。

1
2
> User.create(name: 'Aclice', group_ids: [1, 2, 3])
> User.save

在数据库中,数据以字符串的形式保存:

1
2
> select * from users;
1|alice|---\n- 1\n- 3\n- 5|2013-12-11 14:18:07.344781|2013-12-11 14:18:07.344781

以正常方式取出数据:

1
2
3
4
5
6
7
> user = User.find(1)
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]]
=> #<User id: 1, name: "alice", group_ids: [1, 3, 5], created_at: "2013-12-11 14:18:07", updated_at: "2013-12-11 14:18:07">
> user.group_ids
=> [1, 3, 5]
> user.group_ids.class
=> Array

需要注意的是,serialize 的使用会消耗大量的时间,因此在大部分系统中遭到弃用。

对象类型

可以通过 serialize 所带的第二个参数来指定队形的类型,如 Hash, Array, Json

1
2
3
class User < ActiveRecord::Base
serialize :group_ids, Array
end
1
2
3
> User.create(name: 'bob', group_ids: '1,2,3')
(0.1ms) begin transaction
(0.1ms) rollback transactionActiveRecord::SerializationTypeMismatch: Attribute was supposed to be a Array, but was a String. -- "1,2,3

如果与对象的类型不符,则会显示 ‘ActiveRecord::SerializationTypeMismatch’ 错误。

测试用例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
describe '.serialize' do
let(:user) { build :user }

context 'when group_ids given the Array object' do
subject { user.group_ids }
before do
user.group_ids = [1, 3, 5]
user.save
end
it { should match_array [1,3,5] }
end

context 'when group_ids given an invalid object' do
[12345, 'string value', {key: 'value'}].each do |invalid_object|
before { user.group_ids = invalid_object }
it { expect { user.save }.to raise_error(ActiveRecord::SerializationTypeMismatch) }
end
end
end