Mostrando entradas con la etiqueta ror. Mostrar todas las entradas
Mostrando entradas con la etiqueta ror. Mostrar todas las entradas

jueves, enero 22, 2009

RoR: Agregar FK a una tabla

En RoR resulta muy cómodo utilizar la herramienta rake para manejar la estructura de una BD así como el cambio de versiones. Recientemente me topé con el caso de necesitar agregar una llave externa FK a una tabla existente, en intente hacer la referencia normalmente según rake
ruby script/generate migration add_comment_to_post post:reference
Pero esto no resultó, luego de horas de búsqueda y lectura me doy cuenta que no es posible agregar una FK a una tabla existente utilizando el generador migrate pero que si se puede hacer manualmente y reutilizarse par futuro.

Creemos la migración,
ruby script/generate migration add_post_to_commet


luego vamos a editar db/migrate/XXXX_add_post_to_comment.rb como nos sugiere el nombre, vamos a pasar el id de la tabla post a la tabla comment.
#add_user_to_post.rb
require "migration_helpers"

class AddUserToPost < ActiveRecord::Migration
extend MigrationHelpers

def self.up
#add_foreign_key (:mainentity, :mainentity_id, secundaryentity)
add_foreign_key(:users, :id, :posts)
end

def self.down
#add_foreign_key (:mainentity, :mainentity_id, secundaryentity)
remove_foreign_key(:users, :id, :posts)
end

end
Para comprender lo que acabamos de hacer hay que crear el siguiente helper helpers/migration_helpers.rb
#migration_helpers.rb
module MigrationHelpers

def add_foreign_key(from_table, from_column, to_table, options = {})
constraint_name = foreignkey_name(from_table, to_table)
column_name = foreignkey_column_name(from_table, from_column)

execute %{alter table #{to_table} add #{column_name} INT not null} if options[:add_column]
execute %{alter table #{to_table}
add constraint #{constraint_name} foreign key
#{index_name(column_name)} (#{column_name}) references #{from_table}(#{from_column})
#{ options[:cascade].map{ |cas| " ON #{cas} CASCADE" }.join if options[:cascade] }
}
end

def remove_foreign_key(from_table, from_column, to_table, options = {})
constraint_name = foreignkey_name(from_table, to_table)
column_name = foreignkey_column_name(from_table, from_column)

execute %{alter table #{to_table} drop foreign key #{constraint_name}}
execute %{alter table #{to_table} drop #{column_name}} if options[:remove_column]
end

def create_index(table, *columns)
execute %{create index #{index_name(columns)} on #{table} (#{columns.join(',')}) }
end

def remove_index(table, *columns)
execute %{drop index #{index_name(columns)}on #{table}}
end

private
def foreignkey_column_name(from_table, from_column)
"#{from_table.to_s.singularize}_#{from_column}"
end

def foreignkey_name(from_table, to_table)
"fk_#{from_table}_to_#{to_table}"
end

def index_name(*columns)
"idx_#{columns.join('_')}"
end
end
Con esto estamos listos para hacer
rake db:migrate
y se crea una nueva columna llamada post_id en la tabla comments utilizando rake migrations al igual que se destruye cuando se cambia de version.

La historia completa: http://railsforum.com/viewtopic.php?pid=85698

jueves, enero 10, 2008

RoR: Strike One

Es muy posible que sigan apareciendo artículos como este:

http://www.zedshaw.com/rants/rails_is_a_ghetto.html

Aún no termino de leerlo (son 24 páginas versión impresa) pero han salido a la luz un par de cosas (no puedo decir que si verdaderas) que suceden "hasta en las mejores familias".