2012-03-01 3 views
14

사용자가 제공하지 않는 경우에만 자동 증가 (1001부터 시작)해야하는 token_number 필드가있는 모델 토큰이 있습니다. 문제는 사용자가이 필드를 제공 할 수있는 옵션이 있기 때문에 데이터베이스를 정확히 질의 할 수없고 가장 큰 token_number를 요청할 수 없다는 것입니다. 이 포럼에서 한 가지 답변을 찾았지만 SQL 문을 실행하는 것보다 더 나은 방법이 있어야한다는 것을 확신합니다. Auto increment a non-primary key field in Ruby on Rails레일에 자동 증가 필드 생성

답변

12

나를위한 흥미로운 질문. 불행히도, 레일은 칼럼을 자동 증가시키는 방법을 제공하지 않으므로 우리는 거의 자동화없이 SQL에 의존해야합니다. 내 데이터베이스로의 PostgreSQL을 사용하여 레일 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 

샘플 실행. 첫 번째 토큰의 경우 token_number를 설정하지 않고 token_number 시퀀스를 생성하고 두 번째 토큰은 할당 할 것을 유의하십시오.

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