38

'id'と'language'の2つの列に基づいてレコードの一意のキーを定義したい

ユーザーが次の文字列を送信できるようにするには:id = 1 language = en value = blabla english id = 1 language = fr value = blabla French

set_primary_keyとadd_indexを使用しようとしましたが、機能しませんでした(add_index:words、["id"、 "language_id"]、:unique => true)

私は次のモデルを持っています:

class Word < ActiveRecord::Base
  belongs_to :dictionnary
  belongs_to :language

  attr_accessible :lang, :rev, :value, :dictionnary_id, :language_id

  validates :value, :uniqueness => true

end  

この

class Language < ActiveRecord::Base
    has_many :words

    attr_accessible :lang
end
4

7 に答える 7

54

add_index :words, ["id", "language_id"], :unique => true

動作するはずです。たぶん、あなたはすでにあなたのデータベースにいくつかのユニークでないデータを持っていて、インデックスを作成することができませんか?しかし(@Doonが気付いたように、idは常に一意であるため、冗長になります)。したがって、2つの列に主キーを作成する必要があります。

Railsで2列の主キーを定義するには、次を使用します。

create_table :words, {:id => false} do |t|
  t.integer :id
  t.integer :language_id
  t.string :value
  t.timestamps
end
execute "ALTER TABLE words ADD PRIMARY KEY (id,language_id);"

そして、このgemを使用してモデルにprimary_keyを設定します: http: //rubygems.org/gems/composite_primary_keys

class Word < ActiveRecord::Base
    self.primary_keys = :id,:language_id
end
于 2012-10-05T12:33:01.337 に答える
9

Rails 5では、次のことができます。

create_table :words, primary_key: %i[id language_id] do |t|
  t.integer :id
  t.integer :language_id
  t.string :value
  t.timestamps
end

モデルにprimary_key属性を設定する必要もありません。Word

于 2017-03-23T22:31:27.027 に答える
2

モデル

class User < ActiveRecord::Base
  has_secure_password
  self.primary_keys = :name
end

移行

class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :name, null: false
      t.string :emailid
      t.string :password_digest
      t.integer :locked, :default => 0
      t.text :secretquestion
      t.string :answer

      t.timestamps null: false
    end
    add_index :users, :name, :unique => true
  end
end

あなたはこのテーブルを手に入れるでしょう

画像

于 2016-03-24T07:44:59.243 に答える
1

私のコメントで言ったように、これを試してみるとレールと戦うことになりますが、箱から出してすぐにサポートされるわけではありません。 レールで複合主キーを実行する方法を提供するhttp://compositekeys.rubyforge.orgを見ることができます。まだ必要がないため、使用していません(通常、主キーがなく、結合ペア(HABTM)に一意のインデックスがある単なる結合テーブルのような複合キーであるものがある場合。

于 2012-10-05T12:42:19.810 に答える
0

ユースケースによっては、複合主キーを定義できる複合キーgemを試してみて、ActiveRecordがこの種のモデルを処理できるようにすることもできます(このモデルへの関連付けやurl_forヘルパーなどに大いに役立ちます)。

したがって、このモデルを他のRailsモデルと同じように使用することを計画している場合は、gemが大いに役立ちます。

于 2012-10-05T12:43:06.930 に答える
0

サイトをRailsに移行するときに、同様の問題に直面しました。私のサイトが利用できる各言語のテキストデータを格納するテーブルがあったので、次のようなものがありました。

CREATE TABLE Project_Lang(
    project_id INT NOT NULL,
    language_id INT NOT NULL,
    title VARCHAR(80),
    description TEXT,

    PRIMARY KEY pk_Project_Lang(project_id, language_id),

    FOREIGN KEY fk_Project_Lang_Project(project_id)
        REFERENCES Project(project_id)
        ON DELETE RESTRICT ON UPDATE CASCADE,

    FOREIGN KEY fk_Project_Lang_Language(language_id)
        REFERENCES Language(language_id)
        ON DELETE RESTRICT ON UPDATE CASCADE
)ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 DEFAULT COLLATE = utf8_spanish_ci;

しかし、Railsは箱から出して複合主キーを処理しないため、テーブルの構造を変更する必要があり、独自の主キーがありました。

CREATE TABLE Project_Lang(
    project_lang_id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
    project_id INT NOT NULL,
    language_id INT NOT NULL,
    title VARCHAR(80),
    description TEXT,

    UNIQUE INDEX(project_id, language_id),

    FOREIGN KEY fk_Project_Lang_Project(project_id)
        REFERENCES Project(project_id)
        ON DELETE RESTRICT ON UPDATE CASCADE,

    FOREIGN KEY fk_Project_Lang_Language(language_id)
        REFERENCES Language(language_id)
        ON DELETE RESTRICT ON UPDATE CASCADE
)ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 DEFAULT COLLATE = utf8_spanish_ci;

また、重複レコードが挿入されないように、以前に複合主キーを作成した列に一意のインデックスを作成しました。次に、私のRailsモデルでは、次のことができます。

self.primary_key = "project_lang_id"

そして、それはトリックをしました。私が望んでいたものではありませんが、フレームワークと戦うよりはましです。

于 2016-02-16T22:55:58.267 に答える
0

@ rogal111が言ったように、しかし主キーがすでに存在する場合は、これを実行する必要があります

ALTER TABLE sections DROP PRIMARY KEY, ADD PRIMARY KEY(id, workspace_id, section_key);
于 2016-12-01T03:30:12.510 に答える