Zdefiniuj unikalny klucz podstawowy oparty na 2 kolumnach
Chciałbym zdefiniować unikalny klucz dla rekordów oparty na 2 kolumnach: 'id' i 'language'
Aby użytkownik mógł przesłać następujące ciągi : id = 1 language = en value=blabla english id = 1 language = fr value=blabla french
Próbowałem użyć set_primary_key i add_index, ale nie zadziałało (add_index :words, ["id", "language_id"], :unique => true)
Mam następujący model:
class Word < ActiveRecord::Base
belongs_to :dictionnary
belongs_to :language
attr_accessible :lang, :rev, :value, :dictionnary_id, :language_id
validates :value, :uniqueness => true
end
I to
class Language < ActiveRecord::Base
has_many :words
attr_accessible :lang
end
7 answers
add_index :words, ["id", "language_id"], :unique => true
Aby zdefiniować 2-kolumnowy klucz podstawowy w rails użyj:
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);"
I ustaw primary_key w swoim modelu za pomocą tego klejnotu: http://rubygems.org/gems/composite_primary_keys :
class Word < ActiveRecord::Base
self.primary_keys = :id,:language_id
end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-05 12:45:05
W Rails 5 możesz wykonać następujące czynności:
create_table :words, primary_key: %i[id language_id] do |t|
t.integer :id
t.integer :language_id
t.string :value
t.timestamps
end
Nie jest również konieczne ustawianie atrybutu primary_key
w modelu Word
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-14 15:02:20
Jak już powiedziałem w komentarzach, będziesz walczył z rails, jeśli spróbujesz tego, a to nie jest naprawdę wspierane po wyjęciu z pudełka. możesz spojrzeć na http://compositekeys.rubyforge.org, który oferuje sposób wykonywania kompozytowych kluczy podstawowych w rails. Nie używałem go, ponieważ nie miałem jeszcze potrzeby (zwykle, gdy mam coś, co jest kluczem kompozytowym, jak to jest po prostu tablica złączeń bez klucza podstawowego i unikalny indeks na połączonej parze (HABTM).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-05 12:42:19
Model
class User < ActiveRecord::Base
has_secure_password
self.primary_keys = :name
end
Migracja
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
Dostaniesz tę tabelę
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-28 11:20:41
W zależności od przypadku użycia możesz wypróbować composite key gem, który pozwala zdefiniować złożone klucze podstawowe, a także ehan ActiveRecord do radzenia sobie z tego typu modelem (bardzo pomaga w skojarzeniach z tym modelem lub dla helperów url_for itp.).
Więc jeśli planujesz używać tego modelu jak każdego innego modelu rails, gem bardzo pomoże.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-05 12:43:06
Napotkałem podobny problem podczas migracji witryny do Rails. Miałem tabelę, która przechowuje dane tekstowe dla każdego języka moja strona jest dostępna w więc miałem coś takiego:
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;
Ale ponieważ Rails nie obsługuje złożonych kluczy podstawowych po wyjęciu z pudełka, musiałem zmienić strukturę tabeli, aby miała swój własny klucz podstawowy:
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;
Utworzyłem również unikalny indeks dla kolumn, które wcześniej tworzyły złożony klucz główny, tak aby nie wstawiano zduplikowanego rekordu. Następnie w moim modelu Rails mogłem po prostu:
self.primary_key = "project_lang_id"
I to załatwiło sprawę. To nie jest to, czego chciałem, ale jest lepsze niż walka z ramami.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-16 22:55:58
Tak jak powiedział @rogal111, ale jeśli klucz podstawowy już istnieje, będziesz chciał to zrobić
ALTER TABLE sections DROP PRIMARY KEY, ADD PRIMARY KEY(id, workspace_id, section_key);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-01 03:30:12