我非常高興在宣布Rails 4.0 現(xiàn)在支持 PostgreSQL 數(shù)組類型. 你可以方便的在migration通過 :array => true里創(chuàng)建數(shù)組類型的字段. 創(chuàng)建數(shù)組類型的字段的時候還可以添加其它的選項(length,default,等等)
create_table :table_with_arrays do |t|
t.integer :int_array, :array => true
# integer[]
t.integer :int_array, :array => true, :length => 2
# smallint[]
t.string :string_array, :array => true, :length => 30
# char varying(30)[]
end
需要注意在是對數(shù)組類型的字段設(shè)置默認(rèn)值的時候,你應(yīng)該用Postgresql里的寫法({value,another value}), 如果你想設(shè)置數(shù)組類型的字段默認(rèn)值為空數(shù)組的時候,你應(yīng)該使用:default => '{}'
create_table :table_with_arrays do |t|
t.integer :int_array, :array => true, :default => '{}'
# integer[], default == []
t.integer :int_array, :array => true, :length => 2, :default => '{1}'
# smallint[], default == [1]
end
在Model里使用Postgresql數(shù)組的例子
我們現(xiàn)在有個包含first_name, last_name, nickname的user model, 其中nickname字段是數(shù)組類型. 下面的migration代碼會創(chuàng)建相應(yīng)的表:
create_table :users do |t|
t.string :first_name
t.string :last_name
t.string :nicknames, :array => true
end
并且對于這個表,我們有個簡單的model
class User ActiveRecord::Base
attr_accessible :first_name, :last_name, :nicknames
end
我們沒有對字段使用默認(rèn)值,如果我們實例一個User 對象,代碼是這樣的.
john = User.create(:first_name => 'John', :last_name => 'Doe')
如果,我們調(diào)用john.nickname, 結(jié)果會返回nil, 并且在postgreSQL 里存儲的是NULL值.
我們通過下面的代碼可以在創(chuàng)建時,設(shè)置nickname屬性值
john = User.create(:first_name => 'John', :last_name => 'Doe',
:nicknames => ['Jack', 'Johnny'])
如果我們從數(shù)據(jù)庫獲取記錄,那么nick_name字段會轉(zhuǎn)變成一個數(shù)組,而不是返回字符串{Jack, Johnny}!。Rails 4.0擁有一個純Ruby數(shù)組轉(zhuǎn)換器,但是如果你想讓轉(zhuǎn)換過程加速,那么就可以使用之前提到的 pg_array_parser gem。PgArrayParser 擁有一個基于C的擴(kuò)展,還有一個JRuby的Java的實現(xiàn)(即使這個gem現(xiàn)在在JRuby上存在些問題,我正在嘗試去解決這個問題。)
有一個重點需要注意的,就是當(dāng)在一個model中和數(shù)組(或者其他可變數(shù)值)交互的時候。ActiveRecord現(xiàn)在并沒有跟蹤"destructive",或者更改發(fā)生的地方。這包括數(shù)組的push和pop操作。如果你需要使用"destructive"更新,你必須使用call屬性>_will_change!這樣可以讓ActiveRecord知道你需要更改屬性的值。對于我們的這個User model,如果你想在nickname后面追加元素,你可以這樣做:
john = User.first
john.nicknames += ['Jackie boy']
# 或者
john.nicknames = john.nicknames.push('Jackie boy')
# 任何時候,屬性通過"="賦值,ActiveRecord會跟蹤這個更改
john.save
john.reload
john.nicknames
#=> ['Jack', 'Johnny', 'Jackie Boy']
john.nicknames.pop
john.nicknames_will_change!
# '#pop'操作會改變數(shù)組的值,所以我們需要告訴ActiveRecord它將會發(fā)生更改
john.save
最后一項在Postgresql中使用數(shù)組要注意的事情是: 數(shù)組沒有元素數(shù)量限制,可以是多維數(shù)組,但是在使用多維數(shù)組時, 子數(shù)組元素個數(shù)必須是一樣的.
[[1,2,3], [2,3,4], [4,5,nil]]
# 在PostgreSQL 可用,每個子數(shù)組元素個數(shù)一樣
[1,2,[3,4]]
# 不可用的數(shù)組
您可能感興趣的文章:- PostgreSQL中使用數(shù)組改進(jìn)性能實例代碼
- Mybatis調(diào)用PostgreSQL存儲過程實現(xiàn)數(shù)組入?yún)鬟f
- 在PostgreSQL中使用數(shù)組時值得注意的一些地方
- PostgreSQL 對數(shù)組的遍歷操作