代码之家  ›  专栏  ›  技术社区  ›  corroded

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

  •  24
  • corroded  · 技术社区  · 15 年前

    rake db:seed用应用程序的默认数据库值填充数据库,对吗?所以,如果您已经有了一个种子,并且需要添加它(您添加了一个需要种子的新特性),该怎么办?在我的经验中,当我再次运行rake db:seed时,它添加了已经存在的内容,因此现有内容变成了双倍。

    我需要的是添加一些种子,当运行时,它应该只添加最新的种子,而忽略现有的种子。我该怎么办?(我通常采用的肮脏的、无意义的方法是截断整个数据库,然后再次运行seed,但在生产中这样做不是很明智,对吗?)

    8 回复  |  直到 10 年前
        1
  •  13
  •   Jesse Wolgamott    15 年前

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

    在种子中:

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

    你可以变得更有趣,但在这种情况下,你可以根据需要再次运行它。

        2
  •  38
  •   sscirrus    14 年前

    一个更简单的方法是使用 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. 注意,如果只满足其中一个用户名/角色条件,它将创建上述记录。使用正确的标准以确保不会复制要保持唯一性的内容。
        3
  •  7
  •   Lexun    13 年前

    另一个可能有轻微性能优势的选项:

    # 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调用就可以得到一个存在的数组,然后你只需要在不存在并且需要创建的情况下再次调用。

        4
  •  1
  •   Andrew Kothmann    13 年前

    我对这类事情的偏好是创建一个定制的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

        5
  •  0
  •   Rafael Perea    13 年前

    添加


    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}
    

    这是一个简单的例子,


    更新/重命名


    部门=[“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 否则肯定会发生重复。

    工作: 添加验证唯一性验证或唯一性验证比较所有必要的属性,但不使用 methods skipping validations .

        6
  •  0
  •   coderVishal    11 年前

    一个真正的黑客方法是评论现有的数据,我就是这样做的,对我来说很好。

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

    完成后,删除注释

        7
  •  -1
  •   Stefan Ciprian Hotoleanu    10 年前

    另一个微不足道的选择:

    #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
    
        8
  •  -4
  •   Aitul    13 年前

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