Fremmednøkler i Rails
Av en eller annen grunn har ikke folkene bak Rails mye til overs for fremmednøkler. Heldigvis finnes det løsninger for oss som syntes at dataintegritet er viktigere enn å være database-agnostisk.
Rails 2 lurer deg
I Rails 2 kan du gjøre følgende i migrations:
create_table :employee do |t|
t.references :company
end
Men ikke la deg lure; references gjør stort sett ikke annet enn å lage et integer-felt ved navn company_id. Ingen fremmednøkkel blir opprettet.
Mange løsninger
Det er forholdsvis simpelt å jobbe seg rundt. Tidligere har jeg ofte brukt RedHills plugin for fremmednøkler i migrations, og den funker bra. Idag kom jeg tilfeldigvis over en annen løsning som er litt simplere på railsforum.com:
[RAILS_ROOT]/lib/migration_helpers.rb:
# http://www.railsforum.com/viewtopic.php?pid=59362, noe modifisert
module MigrationHelpers
def add_foreign_key(from_table, from_column, to_table)
constraint_name = "fk_#{from_table}_#{from_column}"
execute "alter table #{from_table} add constraint #{constraint_name} " +
"foreign key (#{from_column}) references #{to_table}(id)"
end
def remove_foreign_key(from_table, from_column)
constraint_name = "fk_#{from_table}_#{from_column}"
execute "alter table #{from_table} drop foreign key #{constraint_name}"
end
end
Deretter kan du gjøre følgende i migrations:
class CreateEmployees < ActiveRecord::Migration
def self.up
create_table :employees do |t|
t.references :company
t.string :name
end
add_foreign_key :employees, :company_id, :companies
end
def self.down
# Ikke egentlig nødvendig når du fjerner tabellen, men...
remove_foreign_key :employees, :company_id
drop_table :employees
end
end
Dette fungerer aldeles glimrende. Du kan også legge til fremmednøkler til eksisterende tabeller (med eksisterende data) gjennom migrations på denne måten også. RedHill-pluginen funker fortsatt, men dette er litt mindre kode, og en litt simplere løsning.
NB! Denne løsningen er MySQL-spesifikk, så tilpass til egne behov.
Kommentarer
Håkon
30. april, 16:20
mvh
Håkon
Christian
1. mai, 22:11
class Car < AciveRecord::Base
has_one :interior_color, :class => 'Color', :foreign_key => 'interior_color_id'
has_one :exterior_color, :class => 'Color', :foreign_key => 'exterior_color_id'
end
http://api.rubyonrails.org/classe...sociations/ClassMethods.html#M001104
(Desverre støtter kommentarfeltet mitt foreløpig kun ren tekst...)
Kommentarer er stengt