2011-01-24 50 views
4

我想在我的Rails應用程序中使用ActiveRecord,但是我想要在PostgreSQL數據庫中而不是在ActiveRecord模型中編碼數據約束。ActiveRecord + postgresql +數據限制

舉例來說,如果我有一個支架生成的模型,

rails generate scaffold User name:string email:string yearofbirth:integer 

我會想,以確保該名稱是相當長的。例如

class User < ActiveRecord::Base 
    validates :name, :length => { :maximum => 140 } 
    validates_uniqueness_of :name 
    validates_numericality_of :yearofbirth, :greater_than_or_equal_to => 1900 
end 

這些驗證很好,因爲如果有人試圖添加壞數據,ActiveRecord會向視圖拋出一些不錯的錯誤消息。但是,我想將規則編碼到數據庫本身,並讓數據庫向ActiveRecord拋出相同的好看和信息錯誤消息,然後將它們傳遞給視圖層。例如,

create table "Users" (
    id integer unique, 
    name varchar(140) unique check(length(name)<140), 
    email varchar(255), 
    yearofbirth integer check (yearofbirth >= 1900) 
); 

我需要什麼PostgreSQL中或ActiveRecord的做才能讓這種情況發生?當我用pgAdmin III工具嘗試它時,它拋出錯誤消息,但我想定製它們。

此外,有沒有辦法將這些數據庫規則正確編碼到Ruby中的數據庫遷移文件中?

我很感激你能給我的任何幫助。

+3

+1:限制對數據應始終處於DB,然後自動添加到ActiveRecord模型。 Rails和ActiveRecord只是訪問我們數據的一種方式,而不是唯一的強制檢查點。這確保了完整性並尊重DRY原則。因此你的問題很有意思,任何好的答案也是如此。 – lkuty 2011-12-15 12:50:19

回答

1

上述CREATE TABLE聲明唯一錯誤的是USER是保留字,必須加引號。因此,

CREATE TABLE "User" (...); 

將工作。 (選擇您想要的名稱的大小寫。)

+0

謝謝。我做了更正。您是否有機會知道如何從約束違規中獲取自定義錯誤消息? – 2011-01-25 15:43:26

1

事實上,您應該有表用戶,在其他情況下,您可以得到更多的問題。 當然你可以定義其他的變形,但它只是錯誤的而不是鐵軌。

class User 
    ... 
end 

然後 創建表用戶 ...

1

下面是使用Oracle(未PostgreSQL系統)的例子,但這個想法是一樣的。只有目錄不同。請注意,我爲非空約束命名了我的約束「table_column_nn」。下面的解決方案可能可以改進。

說的模型Author表示作者不應該有一個NULL名稱。

class Author < ActiveRecord::Base 
    has_and_belongs_to_many :books 

    r = ActiveRecord::Base.connection.select_one("select CONSTRAINT_NAME from user_constraints where TABLE_NAME = 'AUTHORS' and constraint_name like '%_NN'") 
    m = r["constraint_name"].match(/^[^_]*_([^_]*)_NN$/) 
    if !m.nil? 
    column = m[1] 
    validates column.downcase.to_sym, :presence => true 
    end 
end 

的SQL腳本設置的模式是:

create table authors (
    id integer primary key, 
    name varchar2(100) constraint authors_name_nn not null, 
    updated_at timestamp with local time zone, 
    created_at timestamp with local time zone 
); 

單獨的SQL請求對數據庫給出了這樣:

select constraint_name, search_condition from user_constraints where table_name = 'AUTHORS' and constraint_name like '%_NN'; 
CONSTRAINT_NAME  SEARCH_CONDITION 
---------------  ---------------------- 
AUTHORS_NAME_NN  "NOM" IS NOT NULL 

1 row selected.