附加到rake db:seed并在rails中运行而不复制数据

Rake db:seed用应用程序的默认数据库值填充你的数据库吧? 那么,如果您已经有一个种子并且需要添加它(您添加了一个需要种子的新function)。 根据我的经验,当我再次运行rake db:seed时,它已经添加了现有内容,因此现有内容变为了两倍。

我需要的是添加一些种子,当它运行时,它应该只添加最新的种子,并忽略现有的种子。 我该如何解决这个问题? (我通常这样做的脏,noob方式是截断我的整个数据库然后再次运行种子,但是在生产中这不是很聪明,对吧?)

我这样做……当我需要添加用户时

在seeds.rb中:

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

你可以获得更多有趣的东西,但在这种情况下,你可以根据需要重新运行它。

find_or_create_by方法是使用find_or_create_by ,如下所示:

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

以下是可能的结果:

  1. 存在用户名“admin”和角色“admin”的记录。 如果新电子邮件已存在,则不会使用新电子邮件更新此记录,但也不会加倍。
  2. 用户名“admin”和角色“admin”不存在记录。 将创建上述记录。
  3. 请注意,如果只满足其中一个用户名/角色条件,则会创建上述记录。 使用正确的标准可确保您不会复制要保持唯一的内容。

另一种可能带来轻微性能优势的选择:

 # 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 

我认为这样做,你只需要做一个db调用来获取存在的数组,然后你只需要再次调用,如果不存在并且需要创建。

我喜欢这种事情是创建一个自定义rake任务而不是使用seeds.rb文件。

如果您正在尝试批量创建用户,我将使用数据创建.csv文件,然后创建一个名为import_users的rake任务并将其传递给文件名。 然后循环它以创建用户记录。

在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


添加


 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数组的元素,否则肯定会发生重复。

解决方法:添加validates_uniqueness_ofvalidation或比较所有必要属性的唯一性validation但不使用跳过validation的方法 。

一个真正可以理解的方法是评论现有数据,这就是我做的方式,它对我来说很好

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

完成后,只需删除评论

另一个琐碎的选择:

 #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 

只需添加User.delete_all以及seed.rb文件开头的应用程序中包含的所有模型。 肯定不会有任何重复的值。