¿Cuál es la mejor manera de generar una base de datos en Rails?

82

Tengo una tarea de rake que llena algunos datos iniciales en mi aplicación de rieles. Por ejemplo, países, estados, operadores de telefonía móvil, etc.

La forma en que lo tengo configurado ahora es que tengo un montón de declaraciones de creación en archivos en / db / fixtures y una tarea de rake que las procesa. Por ejemplo, un modelo que tengo son los temas. Tengo un archivo theme.rb en / db / fixtures que se ve así:

Theme.delete_all
Theme.create(:id => 1, :name=>'Lite', :background_color=>'0xC7FFD5', :title_text_color=>'0x222222',
                      :component_theme_color=>'0x001277', :carrier_select_color=>'0x7683FF', :label_text_color=>'0x000000',
                      :join_upper_gradient=>'0x6FAEFF', :join_lower_gradient=>'0x000000', :join_text_color=>'0xFFFFFF',
                      :cancel_link_color=>'0x001277', :border_color=>'0x888888', :carrier_text_color=>'0x000000', :public => true)

Theme.create(:id => 2, :name=>'Metallic', :background_color=>'0x000000', :title_text_color=>'0x7299FF',
                      :component_theme_color=>'0xDBF2FF', :carrier_select_color=>'0x000000', :label_text_color=>'0xDBF2FF',
                      :join_upper_gradient=>'0x2B25FF', :join_lower_gradient=>'0xBEFFAC', :join_text_color=>'0x000000',
                      :cancel_link_color=>'0xFF7C12', :border_color=>'0x000000', :carrier_text_color=>'0x000000', :public => true)

Theme.create(:id => 3, :name=>'Blues', :background_color=>'0x0060EC', :title_text_color=>'0x000374',
                      :component_theme_color=>'0x000374', :carrier_select_color=>'0x4357FF', :label_text_color=>'0x000000',
                      :join_upper_gradient=>'0x4357FF', :join_lower_gradient=>'0xffffff', :join_text_color=>'0x000000',
                      :cancel_link_color=>'0xffffff', :border_color=>'0x666666', :carrier_text_color=>'0x000000', :public => true)
puts "Success: Theme data loaded"

La idea aquí es que quiero instalar algunos temas de stock para que los usuarios comiencen. Tengo un problema con este método.

Configurar el ID no funciona. Esto significa que si decido agregar un tema, llamémoslo 'Rojo', entonces simplemente me gustaría agregar la declaración del tema a este archivo de accesorio y llamar a la tarea rake para reiniciar la base de datos. Si hago eso, debido a que los temas pertenecen a otros objetos y su identificación cambia en esta reinicialización, todos los enlaces se rompen.

Mi pregunta es, en primer lugar, ¿es esta una buena manera de manejar la siembra de una base de datos? En un post anterior me lo recomendaron.

Si es así, ¿cómo puedo codificar las ID? ¿Hay alguna desventaja?

Si no es así, ¿cuál es la mejor manera de sembrar la base de datos?

Realmente agradeceré las respuestas largas y bien pensadas que incorporen las mejores prácticas.

Tony
fuente

Respuestas:

113

Actualizando ya que estas respuestas están un poco desactualizadas (aunque algunas aún se aplican).

Característica simple agregada en rails 2.3.4, db / seeds.rb

Proporciona una nueva tarea de rastrillo

rake db:seed

Bueno para completar registros estáticos comunes como estados, países, etc.

http://railscasts.com/episodios/179-seed-data

* Tenga en cuenta que puede usar accesorios si ya los había creado para completar también con la tarea db: seed poniendo lo siguiente en su archivo seeds.rb (del episodio railscast):

require 'active_record/fixtures'
Fixtures.create_fixtures("#{Rails.root}/test/fixtures", "operating_systems")

Para Rails 3.x, use 'ActiveRecord :: Fixtures' en lugar de la constante 'Fixtures'

require 'active_record/fixtures'
ActiveRecord::Fixtures.create_fixtures("#{Rails.root}/test/fixtures", "fixtures_file_name")
ajhit406
fuente
28

Por lo general, se requieren 2 tipos de datos de semillas.

  • Datos básicos en los que puede basarse el núcleo de su aplicación. Yo llamo a esto las semillas comunes.
  • Datos ambientales , por ejemplo, para desarrollar la aplicación, es útil tener un montón de datos en un estado conocido que podamos usar para trabajar en la aplicación localmente (la respuesta de Factory Girl anterior cubre este tipo de datos).

En mi experiencia, siempre me encontré con la necesidad de estos dos tipos de datos. Así que armé una pequeña joya que extiende las semillas de Rails y le permite agregar múltiples archivos de semillas comunes en db / seeds / y cualquier dato de semillas ambientales en db / seeds / ENV, por ejemplo, db / seeds / development.

He descubierto que este enfoque es suficiente para darle a mis datos semilla algo de estructura y me da el poder de configurar mi entorno de desarrollo o preparación en un estado conocido simplemente ejecutando:

rake db:setup

Los accesorios son frágiles y fáciles de mantener, al igual que los volcados de sql regulares.

james2m
fuente
Me gustan los términos "datos del sistema" y "datos en tiempo de ejecución" para describir cosas en las que el código se basa en los datos existentes frente a los de los usuarios. A veces, la línea entre ellos es borrosa.
Tim Abell
27

factory_bot parece que hará lo que estás tratando de lograr. Puede definir todos los atributos comunes en la definición predeterminada y luego anularlos en el momento de la creación. También puede pasar una identificación a la fábrica:

Factory.define :theme do |t|
  t.background_color '0x000000'
  t.title_text_color '0x000000',
  t.component_theme_color '0x000000'
  t.carrier_select_color '0x000000'
  t.label_text_color '0x000000',
  t.join_upper_gradient '0x000000'
  t.join_lower_gradient '0x000000'
  t.join_text_color '0x000000',
  t.cancel_link_color '0x000000'
  t.border_color '0x000000'
  t.carrier_text_color '0x000000'
  t.public true
end

Factory(:theme, :id => 1, :name => "Lite", :background_color => '0xC7FFD5')
Factory(:theme, :id => 2, :name => "Metallic", :background_color => '0xC7FFD5')
Factory(:theme, :id => 3, :name => "Blues", :background_color => '0x0060EC')

Cuando se usa con faker, puede poblar una base de datos muy rápidamente con asociaciones sin tener que meterse con Fixtures (puaj).

Tengo un código como este en una tarea de rake.

100.times do
    Factory(:company, :address => Factory(:address), :employees => [Factory(:employee)])
end
Odia_
fuente
11
FactoryGirl en realidad está diseñado para pruebas en lugar de accesorios, pero también puede usarse para cargar cosas en producción. Utilice una tarea de rake que tenga db: migrate como requisito previo para cargar todos los datos predeterminados. Es posible que deba hacer que la tarea de rake sea lo suficientemente inteligente como para que no cree copias de los datos existentes.
Bob Aman
2
No se recomienda usar FactoryGirl para semillas, consulte esta publicación .
blackbiron
26

Usando seeds.rbarchivo oFactoryBot es excelente, pero estos son respectivamente excelentes para estructuras de datos fijas y pruebas.

La seedbankgema podría darle más control y modularidad a sus semillas. Inserta tareas de rastrillo y también puede definir dependencias entre sus semillas. Su lista de tareas de rake tendrá estas adiciones (por ejemplo):

rake db:seed                    # Load the seed data from db/seeds.rb, db/seeds/*.seeds.rb and db/seeds/ENVIRONMENT/*.seeds.rb. ENVIRONMENT is the current environment in Rails.env.
rake db:seed:bar                # Load the seed data from db/seeds/bar.seeds.rb
rake db:seed:common             # Load the seed data from db/seeds.rb and db/seeds/*.seeds.rb.
rake db:seed:development        # Load the seed data from db/seeds.rb, db/seeds/*.seeds.rb and db/seeds/development/*.seeds.rb.
rake db:seed:development:users  # Load the seed data from db/seeds/development/users.seeds.rb
rake db:seed:foo                # Load the seed data from db/seeds/foo.seeds.rb
rake db:seed:original           # Load the seed data from db/seeds.rb
Yuri
fuente
1

Rails tiene una forma integrada de generar datos como se explica aquí .

Otra forma sería utilizar una gema para una siembra más avanzada o sencilla como: banco de semillas .

La principal ventaja de esta gema y la razón por la que la uso es que tiene capacidades avanzadas, como dependencias de carga de datos y datos semilla por entorno.

Agregando una respuesta actualizada ya que esta respuesta fue la primera en Google.

SimonW
fuente
-3

La mejor forma es utilizar accesorios.

Nota: Tenga en cuenta que los accesorios hacen inserciones directas y no usan su modelo, por lo que si tiene devoluciones de llamada que completan datos, deberá encontrar una solución alternativa.

p01nd3xt3r
fuente
-4

Agréguelo en las migraciones de bases de datos, de esa manera todos lo obtienen a medida que se actualizan. Maneje toda su lógica en el código ruby ​​/ rails, para que nunca tenga que meterse con configuraciones de ID explícitas.

Matt Rogish
fuente
Si necesito cambiar los datos iniciales, las cosas pueden complicarse al usar migraciones. su segundo comentario realmente no tiene sentido. los enlaces a través de claves externas serán destruidos
Tony
c = Category.create (cosas) p = Post.create (cosas) p.category = c No es necesario establecer identificaciones explícitamente. Si cambia los datos iniciales, simplemente crea una nueva migración. Muy fácil.
Matt Rogish
es decir, asumiendo que las asociaciones se pueden realizar en el momento en que se crea el objeto. aquí hay un ejemplo en el que creo que su lógica falla ... corríjame si me equivoco. Siembro la base de datos con temas de plantilla. user id = 1 crea la plantilla id = 2 y con theme id = 4. en este punto, un registro está en la base de datos de la siguiente manera: template: id = 2, user_id = 1, theme_id = 4. ahora, si reinicio la base de datos, theme id = 4 ahora es theme id = 10 ... y luego la plantilla del usuario tiene un tema incorrecto
Tony
bueno, depende de lo que quieras decir con "reiniciar": si comienzas desde cero, Rails maneja todas las asociaciones de forma automática. Si está codificando valores de ID de forma rígida (¡¡¡mal !!!), entonces sí, explotará.
Matt Rogish
ok, estoy empezando a ver su punto, pero tengo que ejecutar este escenario por usted. Siembro la base de datos con una tabla de búsqueda de países. EE. UU. => Id de país = 1. luego, un usuario crea un restaurante que existe en los EE. UU. la fila de la base de datos del restaurante tiene country_id = 1. esto es muy común, ¿verdad? Más tarde decido que quiero agregar más países ... si limpio la base de datos y repoblo la tabla de búsqueda de países, ahora el país de los restaurantes ya no es exacto a menos que la identificación sea la misma. ¿Cómo manejo esto?
Tony