2012-03-01 92 views
14

我有一個模型令牌,它有一個字段token_number,我需要自動增量(從1001開始),當且僅當用戶不提供它時。問題在於,由於用戶可以選擇提供此字段,因此我無法準確查詢數據庫並要求提供最大的令牌編號。我在這個論壇上找到了一個答案,但是我相當肯定,執行SQL語句必須有更好的方法來完成它。 Auto increment a non-primary key field in Ruby on Rails在導軌中生成一個自動增量字段

回答

12

對我有趣的問題。不幸的是,Rails沒有提供自動增加列的方法,所以我們必須儘量少用自動化。我在使用PostgreSQL作爲我的數據庫的Rails 3.0.7嘗試這樣做,它的工作原理,並希望這將是有用的:

爲token_number創建序列現在PGSql Documentation

class CreateTokens < ActiveRecord::Migration 

    def self.up 
    create_table :tokens do |t| 
     t.string :name 
     t.integer :token_number 

     t.timestamps 
    end 

    execute "CREATE SEQUENCE tokens_token_number_seq START 1001" 
    end 

    def self.down 
    drop_table :tokens 

    execute "DROP SEQUENCE tokens_token_number_seq" 
    end 
end 

,因爲沒有被設置token_number的可能性通過用戶手動,我們只需要在沒有設置的情況下生成token_number。 Read about Callbacks here。有了我們,

class Token < ActiveRecord::Base 
    # Generate the sequence no if not already provided. 
    before_validation(:on => :create) do 
    self.application_no = next_seq unless attribute_present?("application_no") 
    end 

    private 
    def next_seq(column = 'application_no') 
     # This returns a PGresult object [http://rubydoc.info/github/ged/ruby-pg/master/PGresult] 
     result = Token.connection.execute("SELECT nextval('tokens_token_number_seq')") 

     result[0]['nextval'] 
    end 
end 

一個示例運行。請注意,對於第一個令牌,我不設置令牌編號,它會生成令牌編號序列,第二個令牌編號。

ruby-1.9.2-p0 > token = Token.new 

=> #<Token id: nil, name: nil, token_number: nil, created_at: nil, updated_at: nil> 
ruby-1.9.2-p0 > token.save 
    SQL (0.8ms) BEGIN 
    SQL (1.7ms) SELECT nextval('tokens_token_number_seq') 
    SQL (6.6ms) SELECT tablename 
FROM pg_tables 
WHERE schemaname = ANY (current_schemas(false)) 

    SQL (33.7ms) INSERT INTO "tokens" ("name", "token_number", "created_at", "updated_at") VALUES (NULL, 1001, '2012-03-02 12:04:00.848863', '2012-03-02 12:04:00.848863') RETURNING "id" 
    SQL (15.9ms) COMMIT 
=> true 
ruby-1.9.2-p0 > token = Token.new 
=> #<Token id: nil, name: nil, token_number: nil, created_at: nil, updated_at: nil> 
ruby-1.9.2-p0 > token.token_number = 3000 
=> 3000 
ruby-1.9.2-p0 > token.save 
    SQL (0.8ms) BEGIN 
    SQL (1.5ms) INSERT INTO "tokens" ("name", "token_number", "created_at", "updated_at") VALUES (NULL, 3000, '2012-03-02 12:04:22.924834', '2012-03-02 12:04:22.924834') RETURNING "id" 
    SQL (19.2ms) COMMIT 
=> true 
ruby-1.9.2-p0 > 
+0

是否有可能以某種方式使用默認值與'nextval'組合以避免使用回調? – freemanoid 2014-09-17 10:26:39