Создать поле автоматического приращения в рельсах - PullRequest
15 голосов
/ 01 марта 2012

У меня есть модель Token, у которой есть поле token_number, которое мне нужно автоматически увеличивать (начиная с 1001), если и только если пользователь не предоставит его.Проблема в том, что, поскольку у пользователя есть возможность предоставить это поле, я не могу точно запросить базу данных и запросить самый большой token_number.Я нашел один ответ на этом форуме, но я вполне уверен, что должен быть лучший способ сделать это, чем выполнить оператор SQL? Автоматически увеличивать поле не первичного ключа в Ruby on Rails

1 Ответ

15 голосов
/ 02 марта 2012

Интересный вопрос для меня. К сожалению, рельсы не предоставляют способ автоматического увеличения столбцов, поэтому мы должны прибегнуть к SQL без особой автоматизации. Я попробовал это в Rails 3.0.7, используя PostgreSQL в качестве базы данных, и он работает, и надеюсь, что это будет полезно:

Создание последовательности для номера токена Документация PGSql

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, только если он не установлен. Читайте о Обратных звонках здесь . С этим мы имеем,

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 > 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...