2012-03-01 84 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