with seeds run rails ruby-on-rails ruby ruby-on-rails-3 seeding

ruby on rails - seeds - añadiendo rake db: seed en rieles y ejecutándolo sin duplicar datos



run seeds rails (8)

Rake db: seed llena su base de datos con los valores predeterminados de la base de datos para una aplicación, ¿verdad? Qué pasa si ya tienes una semilla y necesitas agregarla (agregas una nueva característica que requiere la semilla). En mi experiencia, cuando volví a ejecutar rake db: seed, se agregó el contenido existente, por lo que el contenido existente se duplicó.

Lo que necesito es agregar algunas semillas y cuando se ejecuta, solo debe agregar las más nuevas e ignorar las semillas existentes. ¿Cómo voy con esto? (la forma sucia y noob de la que normalmente lo hago es truncar todo mi db y luego ejecutar seed nuevamente, pero no es muy inteligente hacerlo en la producción, ¿verdad?)


Hago algo como esto ... Cuando necesito agregar un usuario

en seeds.rb:

if User.count == 0 puts "Creating admin user" User.create(:role=>:admin, :username=>''blagh'', :etc=>:etc) end

Puede ser más interesante que eso, pero en este caso, podría volver a ejecutarlo según sea necesario.


Mi preferencia por este tipo de cosas es crear una tarea de rastrillo personalizada en lugar de usar el archivo seeds.rb.

Si está intentando crear usuarios de forma masiva, crearía un archivo .csv con los datos y luego crearía una tarea de rake llamada import_users y le pasaría el nombre del archivo. Luego recorre para crear los registros de usuario.

En lib / tasks / import_users.rake:

namespace :my_app do desc "Import Users from a .csv" task :import_users => :environment do # loop through records and create users end end

Luego ejecute así: rake bundle exec my_app:import_users path/to/.csv

Si necesita ejecutarlo en producción: RAILS_ENV=production bundle exec rake my_app:import_users /path/to/.csv


Otra alternativa trivial:

#categories => name, color categories = [ [ "Category 1", "#e51c23" ], [ "Category 2", "#673ab7" ] ] categories.each do |name, color| if ( Category.where(:name => name).present? == false ) Category.create( name: name, color: color ) end end


Otra opción que podría tener un ligero beneficio de rendimiento:

# This example assumes that a role consists of just an id and a title. roles = [''Admin'', ''User'', ''Other''] existing_roles = Role.all.map { |r| r.title } roles.each do |role| unless existing_roles.include?(role) Role.create!(title: role) end end

Creo que al hacerlo de esta manera, solo tiene que hacer una llamada de db para obtener una matriz de lo que existe, entonces solo tiene que llamar de nuevo si algo no está allí y necesita ser creado.


Simplemente agregue User.delete_all y para todos los modelos que haya incluido en su aplicación al comienzo de su archivo seed.rb. No habrá ningún valor duplicado seguro.


Una forma más limpia de hacerlo es utilizando find_or_create_by , de la siguiente manera:

User.find_or_create_by_username_and_role( :username => "admin", :role => "admin", :email => "[email protected]")

Aquí están los posibles resultados:

  1. Existe un registro con el nombre de usuario "admin" y el rol "admin". Este registro NO se actualizará con el nuevo correo electrónico si ya existe, pero tampoco se duplicará.
  2. No existe un registro con el nombre de usuario "admin" y el rol "admin". Se creará el registro anterior.
  3. Tenga en cuenta que si solo se cumple uno de los criterios de nombre de usuario / rol, se creará el registro anterior. Utilice los criterios correctos para asegurarse de que no está duplicando algo que desea que sea único.

Una forma realmente hackeable sería comentar los datos existentes, así es como lo hice, y funcionó bien para mí

=begin #Commented Out these lines since they where already seeded PayType.create!(:name => "Net Banking") PayType.create!(:name => "Coupouns Pay") =end #New data to be used by seeds PayType.create!(:name => "Check") PayType.create!(:name => "Credit card") PayType.create!(:name => "Purchase order") PayType.create!(:name => "Cash on delivery")

Una vez hecho esto solo quita los comentarios


Añadiendo

desde

departments = ["this", "that"] departments.each{|d| Department.where(:name => d).first_or_create}

a

departments = ["this", "that", "there", "then"] departments.each{|d| Department.where(:name => d).first_or_create}

Este es un ejemplo simple,

Actualizando / renombrando

desde

departments = ["this", "that", "there", "then"] departments.each{|d| Department.where(:name => d).first_or_create}

a

departments = ["these", "those", "there", "then"] new_names = [[''these'', ''this''],[''those'',''that'']] new_names.each do |new| Department.where(:name => new).group_by(&:name).each do |name, depts| depts.first.update_column :name, new[0] if new[1] == name # skips validation # depts[1..-1].each(&:destroy) if depts.size > 1 # paranoid mode end end departments.each{|d| Department.where(:name => d).first_or_create}

IMPORTANTE: debe actualizar los elementos de la matriz de los demás departments contrario, la duplicación seguramente sucederá.

Solución: agregue validates_uniqueness_of validation o una validación de uniquidad comparando todos los atributos necesarios, PERO no use métodos que omitan validaciones .