我正在尝试学习rails,我遇到了一些问题。
我有一个旧的sqlite3数据库,它有一个Accounts
表,我之前用一些GUI程序制作。我想看看我是否可以通过数据库迁移重新创建该表。
以下是我之前的描述(我的目标):
-- desired
CREATE TABLE "accounts" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL DEFAULT (0),
"username" TEXT NOT NULL COLLATE NOCASE,
"password_hash" BLOB NOT NULL,
"creation_time" INTEGER NOT NULL DEFAULT(strftime('%s', 'now')),
"expiration_time" INTEGER NOT NULL DEFAULT(strftime('%s', 'now') + 2592000)
)
我当前的迁移代码无法正常运行。我在某处读到了我可以使用:options
来指定ActiveRecord无法封装的内容,但我可能做错了。当我使用:default => Time.now.to_i
时,它只是硬编码了一些默认值;当我使用:default => "strftime('%s', 'now')"
时,它根本不起作用。
class CreateAccounts < ActiveRecord::Migration
def change
create_table :accounts do |t|
t.column 'username', :text, :null => false, :options => 'COLLATE NOCASE'
t.column 'password_hash', :binary, :null => false
t.column 'creation_time', :integer, :null => false, :options => "DEFAULT(strftime('%s', 'now'))"
t.column 'expiration_time', :integer, :null => false, :options => "DEFAULT(strftime('%s', 'now') + 2592000)"
end
end
end
我最终得到了下表。看起来所有:option
值都被忽略了。
-- what i actually get
CREATE TABLE "accounts" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
"username" text NOT NULL,
"password_hash" blob NOT NULL,
"creation_time" integer NOT NULL,
"expiration_time" integer NOT NULL
)
创建列时如何指定SQL的位数?任何帮助都将非常感激。
答案 0 :(得分:3)
您可以做的最简单的事情就是执行原始SQL来定义表。这看起来像是:
class CreateAccounts < ActiveRecord::Migration
def up
execute <<-SQL
CREATE TABLE "accounts" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL DEFAULT (0),
"username" TEXT NOT NULL COLLATE NOCASE,
"password_hash" BLOB NOT NULL,
"creation_time" INTEGER NOT NULL DEFAULT(strftime('%s', 'now')),
"expiration_time" INTEGER NOT NULL DEFAULT(strftime('%s', 'now') + 2592000)
)
SQL
end
def down
remove_table :accounts
end
end
通过这种方式,您将获得与之前相同的表格。我不完全确定你是否可以用当前的迁移DSL表达这样的表定义。你应该能够验证它。如果您使用上述原始SQL进行迁移,则可以运行rake db:migrate
。这应该生成一个新的db/schema.rb
。然后,您可以打开该文件并搜索帐户表并查看定义。如果包含所有内容,您可以将该定义复制回迁移。
答案 1 :(得分:1)
默认值为:
t.column :creation_time, :integer, :null => false, :default => "strftime('%s', 'now'))"
collate和nocase不能通过ruby完成,但你可以使用execute方法来运行raw sql:
execute "ALTER TABLE accounts ADD COLUMN username TEXT NOT NULL COLLATE NOCASE AFTER id
或者,您可以简单地将排序规则替换为:
class Account < ActiveRecord::Base
def username=(username)
write_attribute :username, username.downcase
end
end
答案 2 :(得分:1)
您的迁移看起来很不错。
由于你确实想学习Rails,我会坚持使用它并尝试解决具体问题。
对于rails,对于创建和更新的日期/时间戳,您要做的是创建名为updated_at和created_at(或每个_on)的字段,然后当rails使用活动记录进行数据库表行更新时,它将适当地更新这些字段并自动(或自动地,如某些人所说)。
这是Rails的基本租户 - 约定优于配置&gt;选择正确的名称和限制,它将为你做“繁重”。
你的问题既使用默认的现在但是硬编码在反思中有意义,但上面的内容将解决它