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

如何将新种子数据添加到现有rails数据库

  •  21
  • toby  · 技术社区  · 11 年前

    我正在开发一个应用程序,该应用程序已经部署到一些测试和暂存系统以及各种开发人员工作站。我需要添加一些额外的参考数据,但我不确定如何添加。

    大多数建议都说使用seed.rb,但我的理解是,当应用程序最初部署时,它只运行一次。既然我们不想仅仅为了添加1行引用数据而重新构建测试和暂存数据库,那么有其他方法可以添加数据吗?

    我正在考虑使用数据库迁移,这是正确的方法吗?

    谢谢

    6 回复  |  直到 11 年前
        1
  •  30
  •   nmott    10 年前

    构造您的seed.rb文件,以允许不断创建和更新数据。您不限于只运行一次种子文件,如果您认为它只用于初始部署,您将错过它在设置参考数据方面所能提供的灵活性。

    种子文件只是ruby,因此您可以执行以下操作:

    user = User.find_or_initialize_by(email: 'bob@example.com')
    user.name = 'Bob'
    user.password = 'secret'
    user.role = 'manager'
    user.save!
    

    如果数据不存在,这将创建新数据,如果发现一些数据,则会更新数据。

    如果种子文件的结构正确,还可以创建和更新从属对象。

    我建议使用bang-save来确保在无法保存对象的情况下引发异常。这是调试种子的最简单方法。

    我使用 seedbank gem 为我的种子数据提供更多的结构,包括按环境设置数据、依赖种子等等。

    我不建议对种子数据使用迁移。缺乏灵活性(例如,如何将种子数据仅针对一个环境),也没有真正的方法来建立一组可随时运行以刷新特定环境的可重用数据。您还将有一组迁移,这些迁移没有引用您的模式,并且每次您想要生成新的或更改当前数据时,都必须创建新的迁移。

        2
  •  2
  •   Miotsu    11 年前

    您可以使用迁移,但这不是最安全的选择。 例如,您通过迁移将一条记录添加到表中,然后在将来更改该表的模式。当你将应用程序安装到某个地方时,你将无法运行 rake db:migrate .

    种子总是可取的,因为 rake db:seed 可以在完全迁移的架构上运行。

    如果只是为了记录,请选择rails控制台。

        3
  •  2
  •   konyak    10 年前

    最好在seed.rb中使用这样的幂等方法,或者在seed.rbs调用的另一个任务中使用:

    Contact.find_by_email("test@example.com") || Contact.create(email: "test@example.com", phone: "202-291-1970", created_by: "System")
    # This saves you an update to the DB if the record already exists.
    

    或者类似于@nmott的:

    Contact.find_or_initialize_by_email("test@example.com").update_attributes(phone: "202-291-1970", created_by: "System")
    # this performs an update regardless, but it may be useful if you want to reset your data.
    

    或使用 assign_attributes 而不是 update_attributes 如果要在保存之前指定多个属性。

        4
  •  1
  •   Steve Carey    8 年前

    我一直使用种子文件将实例添加到新表或现有表中。我的解决方案很简单。我只是注释掉db/seeds.rb文件中的所有其他种子数据,这样只有新的种子数据是活动代码。然后跑步 bin/rake db:seed .

        5
  •  0
  •   Jaga Jugue    10 年前

    我在seed.rb中做了这样的事情

    users_list = [
       {id: 1, name: "Diego", age: "25"},
       {id: 2, name: "Elano", age: "27"}
    ]
    
    while !users_list.empty? do
      begin
        User.create(users_list)
      rescue
        users_list = users_list.drop(1) #removing the first if the id already exist.
      end
    end
    

    如果列表中给定id的项目已经存在,它将返回一个异常,然后我们删除该项目并重试,直到users_list数组为空。

    这样,您就不需要在包含每个对象之前搜索它,但您将无法像@nmott代码中那样更新已经插入的值。

        6
  •  0
  •   ehannes    9 年前

    而不是改变 seeds.db ,您可能想使用它来播种新的数据库,您可以创建一个自定义的Rake任务( RailsCast #66 Custom Rake Tasks ).

    您可以创建任意数量的Rake任务。例如,假设您有两台服务器,一台运行应用程序的1.0版本,另一台运行1.1版本,并且您希望将这两台服务器都升级到1.2版本。然后您可以创建 lib/tasks/1-0-to-1-2.rake lib/tasks`1-1-to-1-2.rake 因为根据应用程序的版本,您可能需要不同的代码。