1

私は Rails を学ぼうとしていますが、ちょっとした問題に遭遇しました。

古い sqlite3 データベースがあり、AccountsGUI プログラムで以前に作成したテーブルがあります。データベースの移行でそのテーブルを再作成できるかどうかを確認したいと思います。

これが私が以前に持っていたものの説明です(私の目標):

-- 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)
)

現在の移行コードが正しく機能しません。ActiveRecordがカプセル化できないものを指定するために使用できる場所を読み:optionsましたが、おそらく間違っています。を使用する: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 を指定するにはどうすればよいですか? どんな助けでも大歓迎です。

4

3 に答える 3

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. その後、そのファイルを開き、accounts テーブルを検索して定義を確認できます。すべてが含まれている場合は、その定義を移行にコピーできます。

于 2012-12-31T14:07:50.787 に答える
1

デフォルトは次のように行われます。

t.column :creation_time, :integer, :null => false, :default => "strftime('%s', 'now'))"

collat​​e と nocase は ruby​​ では実行できませんが、execute メソッドを使用して生の 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
于 2012-12-31T14:07:48.733 に答える
1

あなたの移行はかなり良さそうです。

実際にRailsを学びたいので、私はそれに固執し、特定の問題に対処しようとします.

Railsの場合、作成および更新された日付/タイムスタンプの場合、updated_atおよびcreated_at(またはそれぞれに対して_on)と呼ばれるフィールドを作成し、レールがアクティブレコードを使用してデータベーステーブルの行更新を行うと、それらのフィールドを適切かつ自動的に更新します(または、一部の人が言うように自動的に)。

これは、Rails の基本的なテナントです - 構成よりも慣習です> 適切な名前と構造を選択すると、「面倒な作業」が自動的に行われます。

あなたの問題は両方とも現在のデフォルトを使用していますが、ハードコードされていることはリフレクションでは理にかなっていますが、上記はそれに対処します

于 2012-12-31T14:26:58.647 に答える