Wah*_*Ali 16 ruby-on-rails auto-increment rails-migrations
我有一个模型令牌,它有一个字段token_number,我需要自动递增(从1001开始),当且仅当用户不提供它.问题是,由于用户可以选择提供此字段,因此无法完全查询数据库并请求最大的token_number.我在这个论坛上找到了一个答案,但我确信必须有一个更好的方法来执行它而不是执行SQL语句?在Ruby on Rails中自动增加非主键字段
Sye*_*lam 17
对我来说有趣的问题.遗憾的是,rails并没有提供自动增加列的方法,因此我们必须采用几乎没有自动化的SQL.我在Rails 3.0.7中尝试使用PostgreSQL作为我的数据库并且它有效并且希望这将是有用的:
为token_number 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
Run Code Online (Sandbox Code Playgroud)
现在,由于用户手动设置了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
Run Code Online (Sandbox Code Playgroud)
样本运行.请注意,对于第一个令牌,我没有设置token_number,它会生成token_number序列,而我正在分配第二个令牌.
token = Token.new
# => #<Token id: nil, name: nil, token_number: nil, created_at: nil, updated_at: nil>
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
token = Token.new
# => #<Token id: nil, name: nil, token_number: nil, created_at: nil, updated_at: nil>
token.token_number = 3000
# => 3000
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
Run Code Online (Sandbox Code Playgroud)
另一个选择是将 nextval 设置为 postgresql 中的默认值
这使我们不需要编写回调
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"
execute "ALTER TABLE tokens ALTER COLUMN token_number SET DEFAULT NEXTVAL('tokens_token_number_seq')"
end
def self.down
drop_table :tokens
execute "DROP SEQUENCE tokens_token_number_seq"
end
end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
19844 次 |
| 最近记录: |