добавление рейка db: seed в рельсы и запуск его без дублирования данных - PullRequest
24 голосов
/ 13 августа 2010

Rake db: seed заполняет вашу базу данных значениями базы данных по умолчанию для приложения, верно?Так что, если у вас уже есть семя, и вам нужно добавить к нему (вы добавляете новую функцию, которая требует семя).По моему опыту, когда я снова запустил rake db: seed, он добавил уже существующий контент, так что существующий контент стал двойным.

Мне нужно добавить несколько семян, а при запуске нужно просто добавить самые новыеи игнорировать существующие семена.Как я могу пойти с этим?(Грязный, нубский способ, которым я обычно занимаюсь, - это урезать всю мою базу данных, а затем снова запустить seed, но это не очень разумно делать в производстве, верно?)

Ответы [ 8 ]

38 голосов
/ 31 декабря 2010

Более чистый способ сделать это - использовать find_or_create_by следующим образом:

User.find_or_create_by_username_and_role(
  :username => "admin",
  :role => "admin",
  :email => "me@gmail.com")

Вот возможные результаты:

  1. Существует запись с именем пользователя "admin"и роль" админ ".Эта запись НЕ будет обновлена ​​новым сообщением электронной почты, если оно уже существует, но также НЕ будет удвоено.
  2. Запись не существует с именем пользователя «admin» и ролью «admin».Будет создана вышеуказанная запись.
  3. Обратите внимание, что, если удовлетворен только один из критериев имени пользователя / роли, будет создана вышеуказанная запись.Используйте правильные критерии, чтобы убедиться, что вы не дублируете то, что хотите сохранить уникальным.
13 голосов
/ 13 августа 2010

Я делаю что-то вроде этого .... Когда мне нужно добавить пользователя

в семенах. Rb:

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

Вы можете получить более интересное, чем это, но в этом случае, вы можете запустить его заново при необходимости.

8 голосов
/ 11 декабря 2012

Еще один вариант, который может принести незначительный выигрыш в производительности:

# 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

Я думаю, что для этого вам нужно сделать всего один вызов БД, чтобы получить массив того, что существует, тогда вам нужно толькопозвонить снова, если что-то не существует и его нужно создать.

1 голос
/ 06 сентября 2012

Я предпочитаю создавать подобные задачи, а не использовать файл seed.rb.

Если вы пытаетесь создать массовое создание пользователей, я бы создал файлы .csv с данными, затем создал задачу rake с именем import_users и передал ей имя файла. Затем выполните цикл, чтобы создать пользовательские записи.

В 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

Тогда беги так: rake bundle exec my_app:import_users path/to/.csv

Если вам нужно запустить его в производство: RAILS_ENV=production bundle exec rake my_app:import_users /path/to/.csv

0 голосов
/ 18 ноября 2015

Еще одна банальная альтернатива:

#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
0 голосов
/ 14 мая 2015

По-настоящему хакерским способом было бы закомментировать существующие данные, вот как я это сделал, и это отлично сработало для меня

=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")

После этого просто удалите комментарии

0 голосов
/ 05 сентября 2012

Добавление


от

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

до

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

это простой пример,


Обновление / переименование


от

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

до

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}

ВАЖНО: Вам необходимо обновить элементы массива departments, иначе обязательно произойдет дублирование.

Обход: Добавьте валидацию_uniqueness_of валидации или валидации уникальности, сравнивая все необходимые атрибуты, НО не используйте методы, пропускающие валидации .

0 голосов
/ 15 ноября 2011

Просто добавьте User.delete_all и для всех моделей, которые вы включили в ваше приложение, в начале вашего файла seed.rb. Там не будет никаких повторяющихся значений наверняка.

...