Forum: Rails-ES Re: intentando entender el Rake::Task => poltergeist con el RAILS_ENV

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
6f952bee7570a3db2ecba5b06c0062b3?d=identicon&s=25 Fernando Guillen (fguillen)
on 2009-01-26 20:48
(Received via mailing list)
En el mismo hilo de "intentando entender el Rake::Task".

Ahora, bueno de antes, pero presento mi duda ahora, me encuentro con
que al ejecutar Rake::Tasks['db:migrate'] las migraciones se ejecutan
en una u otra tabla dependiendo de cosas que a primera vista nada
tienen que ver.

Esta es mi rake de ejemplo:
  desc "Run migrations"
  task :run_migrations => [:environment] do
    Rake::Task['db:create:all'].execute
    Rake::Task['db:migrate'].execute
  end

Como veis intenta ejecutar
 $ rake db:create:all
 $ rake db:migrate

Y es eso lo que hace pero las migraciones las corre en la db de test
en vez de la development como vemos a
continuación:
$ rake db:drop:all
(in /Users/fguillen/Documents/develop-ror/euruko_app)
$ rake init:run_migrations > /dev/null
$ ls -l db/
total 88
-rw-r--r--   1 fguillen  staff      0 26 ene 20:39 development.sqlite3
drwxr-xr-x  15 fguillen  staff    510 26 ene 18:50 migrate
-rw-r--r--   1 fguillen  staff      0 26 ene 20:39 production.sqlite3
-rw-r--r--   1 fguillen  staff   5938 26 ene 20:39 schema.rb
-rw-r--r--   1 fguillen  staff  34816 26 ene 20:39 test.sqlite3

Como veis se ha cargado la db test pero las demás están a cero.

Ahora bien.. si saco de la rake el Rake::Task['db:create:all'] ,
entonces la migración la corre en development:

  desc "Run migrations"
  task :run_migrations => [:environment] do
    Rake::Task['db:migrate'].execute
  end

$ rake db:drop:all
$ rake db:create:all
$ rake init:run_migrations > /dev/null
$ ls -l db/
total 88
-rw-r--r--   1 fguillen  staff  34816 26 ene 20:41 development.sqlite3
drwxr-xr-x  15 fguillen  staff    510 26 ene 18:50 migrate
-rw-r--r--   1 fguillen  staff      0 26 ene 20:41 production.sqlite3
-rw-r--r--   1 fguillen  staff   5938 26 ene 20:41 schema.rb
-rw-r--r--   1 fguillen  staff      0 26 ene 20:41 test.sqlite3


Otra prueba curiosa es que si dejamos el db:create:all dentro de la
rake pero las dbs ya existían de antes tenemos que también ejecuta la
migración en la db de development:

  desc "Run migrations"
  task :run_migrations => [:environment] do
    Rake::Task['db:create:all'].execute
    Rake::Task['db:migrate'].execute
  end

$ rake db:drop:all
$ rake db:create:all
$ rake init:run_migrations > /dev/null
db/development.sqlite3 already exists
db/production.sqlite3 already exists
db/test.sqlite3 already exists
$ ls -l db/
total 88
-rw-r--r--   1 fguillen  staff  34816 26 ene 20:43 development.sqlite3
drwxr-xr-x  15 fguillen  staff    510 26 ene 18:50 migrate
-rw-r--r--   1 fguillen  staff      0 26 ene 20:43 production.sqlite3
-rw-r--r--   1 fguillen  staff   5938 26 ene 20:43 schema.rb
-rw-r--r--   1 fguillen  staff      0 26 ene 20:43 test.sqlite3

Entonces al parecer lo que pasa es que 'db:create:all' modifica la
RAILS_ENV y la deja con valor 'test' entonces cuando llega
'db:migrate' ejecuta la migración en test.

He intentado, siguiendo las instrucciones de javi, a hacer esto:

  desc "Run migrations"
  task :run_migrations => [:environment] do
    Rake::Task['db:create:all'].execute
    ENV['RAILS_ENV']='development'
    Rake::Task['db:migrate'].execute
  end

Pero nada :/

Tampoco esto
  desc "Run migrations"
  task :run_migrations => [:environment] do
    Rake::Task['db:create:all'].execute
    RAILS_ENV='development'
    Rake::Task['db:migrate'].execute
  end

Pues eso.. que ni idea que puedo probar ahora.. ¿algún capote? :)

Saludos
f.
1f2eadfb41362800ebc2cf211b91d0f7?d=identicon&s=25 javier ramirez (Guest)
on 2009-01-26 21:02
(Received via mailing list)
> Entonces al parecer lo que pasa es que 'db:create:all' modifica la
> RAILS_ENV y la deja con valor 'test' entonces cuando llega
> 'db:migrate' ejecuta la migración en test.
>

sin ver el fuente  tiene pinta de los conflictos de variables, sí.. no
tengo ni idea de si colará, pero por probar

env_before=ENV.dup
Rake::Task['db:create:all'].execute
ENV=env_before
Rake::Task['db:migrate'].execute

Si ENV no está protegido de alguna forma rara, eso debería ejecutar la
segunda rake con el mismo entorno que la primera

y si no, toca leer el código de las rake de Active Record.

suerte,


--
javier ramírez

..i do ruby on rails development in madrid, spain, at
http://www.aspgems.com
..you can find out more about me on http://formatinternet.wordpress.com
and http://workingwithrails.com/person/5987-javier-ramirez
1f2eadfb41362800ebc2cf211b91d0f7?d=identicon&s=25 javier ramirez (Guest)
on 2009-01-26 21:19
(Received via mailing list)
> env_before=ENV.dup
>
me ha entrado la curiosidad del dup sobre ENV y no va bien porque es un
singleton y el dup no lo hace bien, el clone te devuelve lo mismo y el
Marshal.dump no lo sabe serializar. Pero se puede hacer un volcado tal
que así

 entries_before = ENV.entries
 Rake::Task['db:create:all'].execute
 entries_before.each {|en| ENV[en.first]=en.last}
 Rake::Task['db:migrate'].execute

 Lo de los rake no lo he probado.. pero sí he probado que el ENV se
restaura con esto.

Con el ENV.entries consigues un array con las entradas, que luego
restauras antes de la segunda tarea. El punto débil aquí sería si la
tarea de antes hace set de alguna variable que no estuviera previamente,
porque con esto esas variables no se restaurarían. Si ese fuera el caso,
el reset habría que hacerlo iterando por ENV, comparando con
entries_before, y eliminando las que se hubieran añadido.

Bueno.. no me pico más con esto ;)  ciao!


--
javier ramírez

..i do ruby on rails development in madrid, spain, at
http://www.aspgems.com
..you can find out more about me on http://formatinternet.wordpress.com
and http://workingwithrails.com/person/5987-javier-ramirez
6f952bee7570a3db2ecba5b06c0062b3?d=identicon&s=25 Fernando Guillen (fguillen)
on 2009-01-26 21:24
(Received via mailing list)
El día 26 de enero de 2009 21:02, javier ramirez
<jramirez@aspgems.com>
escribió:> Rake::Task['db:create:all'].execute
> ENV=env_before
> Rake::Task['db:migrate'].execute
>
> Si ENV no está protegido de alguna forma rara, eso debería ejecutar la
> segunda rake con el mismo entorno que la primera

peta:

~/Documents/develop-ror/euruko_app(master) $ rake init:run_migrations
--trace
(in /Users/fguillen/Documents/develop-ror/euruko_app)
** Invoke init:run_migrations (first_time)
** Invoke environment (first_time)
** Execute environment
** Execute init:run_migrations
** Execute db:create:all
db/development.sqlite3 already exists
db/production.sqlite3 already exists
db/test.sqlite3 already exists
** Execute db:migrate
rake aborted!
undefined method `[]' for #<Object:0x1ef125c>
/Library/Ruby/Gems/1.8/gems/rails-2.2.2/lib/tasks/databases.rake:110

>
> y si no, toca leer el código de las rake de Active Record.

Pues sí.. gracias javi.. seguiré informando por aquí

Saludos
f.
49b6123803e4f327144e991daab62f77?d=identicon&s=25 Daniel Rodriguez Troitiño (Guest)
on 2009-01-26 21:24
(Received via mailing list)
2009/1/26 javier ramirez <jramirez@aspgems.com>:
> Rake::Task['db:create:all'].execute
>
Supongo que "test" es el último environment en database.yml.

Según se puede ver en el código, db:create:all itera por cada
environment de database.yml abriendo una conexión nueva a cada base de
datos, pero si mal no veo nunca la cierra, por lo que al realizar la
siguiente tarea utiliza la última conexión abierta, es decir 'test'.
Claramente es un bug en Rails.

Una posible solución entre las dos tareas poner (no lo he probado):

ActiveRecord::Base.connection.disconnect!
ActiveRecord::Base.establish_connection(env['RAILS_ENV'])

Creo que eso conseguiría lo que quieres.

Suerte.
6f952bee7570a3db2ecba5b06c0062b3?d=identicon&s=25 Fernando Guillen (fguillen)
on 2009-01-26 21:54
(Received via mailing list)
El día 26 de enero de 2009 21:19, javier ramirez
<jramirez@aspgems.com>
escribió:>  Rake::Task['db:migrate'].execute
>
> Bueno.. no me pico más con esto ;)  ciao!

Pues espero no seguir picándote y dejarte descansar :).. pero no chuta

He dado un paso más y he comprobado las diferencias en el ENV antes y
despúes de la llamada a db:create:all. y .. ahí no está el problema
pues son exactamente iguales:

  desc "Run migrations"
  task :run_migrations2 => [:environment] do
    entries_before = ENV.entries
    Rake::Task['db:create:all'].execute
    entries_before.each do |en|
      puts "cambio: #{ENV[en.first]} => #{en.last}"  if ENV[en.first] !=
en.last
    end
    Rake::Task['db:migrate'].execute
  end

No devuelve ningún cambio :/

Siguiendo tu consejo anterior y mirando el código estoy viendo que el
create:all recorre todas las configuraciones e invoca a:

            ActiveRecord::Base.establish_connection(config)
            ActiveRecord::Base.connection

Por lo que manda al traste la conexión que haya hecho el :environment
y se queda con la última.. que, advina por donde, es la 'test'.

Entonces al llegar la db:migrate pilla la conexión que esté activa que
casualmente es la 'test' y eso es lo que está pasando..

Ahora a ver como puedo forzar este comportamiento para que pille la
conexión relativa al environment 'development'... y esta es la primera
aproximación:
  desc "Run migrations"
  task :run_migrations2 => [:environment] do
    Rake::Task['db:create:all'].execute

    config = ActiveRecord::Base.configurations[RAILS_ENV]
    ActiveRecord::Base.establish_connection(config)
    ActiveRecord::Base.connection

    Rake::Task['db:migrate'].execute
  end

Donde RAILS_ENV.. lo podemos sustituir por 'development' o lo que
queramos.

.. fin?

:)

Graaaacias

f.
6f952bee7570a3db2ecba5b06c0062b3?d=identicon&s=25 Fernando Guillen (fguillen)
on 2009-01-26 21:55
(Received via mailing list)
El día 26 de enero de 2009 21:23, Daniel Rodriguez
Troitiño<notzcoolx@yahoo.es>
escribió:>> env_before=ENV.dup
>>
> Una posible solución entre las dos tareas poner (no lo he probado):
>
> ActiveRecord::Base.connection.disconnect!
> ActiveRecord::Base.establish_connection(env['RAILS_ENV'])
>
> Creo que eso conseguiría lo que quieres.
>
> Suerte.

Joer Dani.. el más rápido del oeste rails ;P

f.
This topic is locked and can not be replied to.