2012-03-01 14 views
14

Tengo un token de modelo, que tiene un campo número_tabol que necesito aumentar automáticamente (comenzando desde 1001), si y solo si el usuario no lo proporciona. El problema es que, dado que el usuario tiene la opción de proporcionar este campo, no puedo consultar exactamente la base de datos y solicitar el token_number más grande. Encontré una respuesta en este foro, pero estoy bastante seguro de que tiene que haber una forma mejor de hacerlo que ejecutar una declaración SQL. Auto increment a non-primary key field in Ruby on RailsGenerar un campo de incremento automático en rieles

Respuesta

12

Interesante pregunta para mí. Desafortunadamente, los rieles no ofrecen una manera de autoincrementar columnas, por lo que debemos recurrir a SQL con poca automatización. He intentado esto en Rails 3.0.7 utilizando PostgreSQL como mi base de datos y funciona y espero que esto sea útil:

Creación de secuencia para 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 

Ahora, ya que existe una posibilidad de ser fijado token_number por el usuario de forma manual, tendremos que generar el token_number solo si no se está configurando. Read about Callbacks here. Con lo que tenemos,

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 

Un análisis de la muestra. Tenga en cuenta que para el primer token no estoy configurando token_number y genera la secuencia token_number y para el segundo que estoy asignando.

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

¿Es posible de alguna manera usar el valor predeterminado en combinación con 'nextval' para evitar el uso de devoluciones de llamada? – freemanoid

Cuestiones relacionadas