2

私は2つのフィールドを持つモデルを持っています => :name と :age

自動インクリメントが必要で、0 (ゼロ) から始まる列 :position を追加する移行を行う必要があります。

私はこれらの方法を試しました:

class AddPosition < ActiveRecord::Migration
  def up
    add_column :clientes, :position, :integer, :default => 0, :null => false
    execute "ALTER TABLE clientes ADD PRIMARY KEY (position);"
  end

ただし、自動インクリメントではないため機能しません。主キーをタイプとして使用しようとすると:

class AddPosition < ActiveRecord::Migration
  def up
    add_column :clientes, :position, :primary_key, :default => 0, :null => false
  end
end

複数の値があるため、rake db:migrate は実行されません。

Rails 3.2で主キーにゼロと自動インクリメントを設定する方法を説明できる人はいますか?

4

1 に答える 1

2

PostgreSQL で自動インクリメント列を設定する方法は次のとおりです。

# in migration:
def up
  execute <<-SQL
    CREATE SEQUENCE clients_position_seq START WITH 0 MINVALUE 0;
    ALTER TABLE clients ADD COLUMN position INTEGER NOT NULL DEFAULT nextval('clients_position_seq');
  SQL
end

しかし、残念ながら、それはあなたが必要とするものではないかもしれません. clients上記は、次のような SQL を使用してテーブルに値を挿入する場合に機能しますINSERT INTO clients(name, age) VALUES('Joe', 21)が、レールはそのようには機能しません。

最初の問題は、主キーが呼び出されることを Rails が想定していることidです。この規則をオーバーライドすることはできますが、解決するよりも多くの問題が発生します。位置を主キー値にバインドする場合は、次のような方法で仮想属性をモデルに追加することをお勧めします。

def position
  id.nil? ? nil : id - 1
end

しかし、すでに従来の主キーがあり、フィールドidを追加して、作成後にクライアントの ID に触れpositionにクライアントを並べ替えることができるとします(これは常に良い考えです)。ここで 2 番目の問題が発生します。Rails は を認識せず、尊重しません。つまり、PG でサポートされたシーケンスから値を取得せず、デフォルトで入れようとします。DEFAULT nextval('clients_position_seq')NULLposition

より良いオプションとして、 acts_as_list gemを検討することをお勧めします。これにより、DB シーケンスの操作が不要になります。残念ながら1、初期値として使用されますpositionが、リスト位置フィールドにカスタム名を設定し、上記のようにメソッドを定義することで解決できます。

于 2012-09-04T09:18:15.273 に答える