with tutorial framework español djangoproject desde con cero applications ruby-on-rails primary-key composite-primary-key

ruby-on-rails - framework - tutorial django



Definir una clave primaria única basada en 2 columnas (7)

Me gustaría definir una clave única para los registros basados ​​en 2 columnas: ''id'' y ''language''

para permitir que el usuario envíe las siguientes cadenas: id = 1 language = en value = blabla english id = 1 language = fr value = blabla french

Traté de usar set_primary_key y también add_index pero no funcionó (add_index: words, ["id", "language_id"],: unique => true)

Tengo el siguiente modelo:

class Word < ActiveRecord::Base belongs_to :dictionnary belongs_to :language attr_accessible :lang, :rev, :value, :dictionnary_id, :language_id validates :value, :uniqueness => true end

y esto

class Language < ActiveRecord::Base has_many :words attr_accessible :lang end


Como dije en mis comentarios, lucharás contra los rieles si pruebas esto, y no es realmente compatible. puede ver http://compositekeys.rubyforge.org que ofrece una forma de hacer claves primarias compuestas en rieles. No lo he usado, ya que todavía no lo he necesitado (normalmente cuando tengo algo que es una clave compuesta como si fuera solo una tabla de combinación sin clave principal y un índice único en el par unido (HABTM).


Como dijo @ rogal111, pero si ya existe una clave principal, querrás hacer esto

ALTER TABLE sections DROP PRIMARY KEY, ADD PRIMARY KEY(id, workspace_id, section_key);


Dependiendo de su caso de uso, es posible que desee probar la gema de clave compuesta que le permite definir claves primarias compuestas y también mejora ActiveRecord para tratar este tipo de modelo (ayuda mucho a las asociaciones de este modelo o para url_for helpers, etc.).

Entonces, si planea usar este modelo como cualquier otro modelo de rieles, la gema ayudará mucho.


En Rails 5 puedes hacer lo siguiente:

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

Tampoco es necesario establecer el atributo primary_key en el modelo de Word .


Me enfrenté a un problema similar al migrar un sitio a Rails. Tenía una tabla que almacena datos de texto para cada idioma en el que mi sitio está disponible, así que tuve algo como esto:

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;

Pero como Rails no maneja las claves primarias compuestas de la caja, me vi obligado a cambiar la estructura de la tabla para que tuviera su propia clave principal:

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;

También creé un índice único para las columnas que previamente hacían la clave primaria compuesta para que no se inserte ningún registro duplicado. Luego, en mi modelo de Rails, pude simplemente:

self.primary_key = "project_lang_id"

Y ese fue el truco. No es lo que quería, pero es mejor que luchar contra el marco.


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

Deberia de funcionar. Tal vez ya tiene algunos datos no únicos en su base de datos y no se puede crear el índice? Pero (como @Doon notó que será redundante ya que id es siempre único). Entonces necesitas crear la clave principal en dos columnas.

Para definir la clave primaria de 2 columnas en los raíles use:

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

Y configure primary_key en su modelo con esta joya: http://rubygems.org/gems/composite_primary_keys :

class Word < ActiveRecord::Base self.primary_keys = :id,:language_id end


Modelo

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

Migración

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

Obtendrás esta tabla