【问题标题】:Add Rows on Migrations在迁移中添加行
【发布时间】:2010-09-29 17:46:12
【问题描述】:

我想知道在 Rails 迁移中向数据库表添加记录的首选方法是哪种。我在 Ola Bini 的书(Jruby on Rails)上读到他做了这样的事情:

class CreateProductCategories < ActiveRecord::Migration

  #defines the AR class
  class ProductType < ActiveRecord::Base; end

  def self.up

    #CREATE THE TABLES...

    load_data
  end
  def self.load_data
    #Use AR object to create default data
    ProductType.create(:name => "type")
  end
end

这很好,很干净,但由于某种原因,不适用于最新版本的 rails...

问题是,如何使用默认数据(如用户或其他数据)填充数据库?

谢谢!

【问题讨论】:

  • 这就是我所做的,请包括您收到的错误。
  • 完整代码是这样的:pastie.org/pastes/251539 错误是'CreateProductCategories is not missing constant ProductType'
  • 为此使用种子.rb。

标签: ruby-on-rails database migration


【解决方案1】:

用于迁移的 Rails API 文档显示了实现此目的的更简单方法。

http://api.rubyonrails.org/classes/ActiveRecord/Migration.html

class CreateProductCategories < ActiveRecord::Migration
  def self.up
    create_table "product_categories" do |t|
      t.string name
      # etc.
    end

    # Now populate the category list with default data

    ProductCategory.create :name => 'Books', ...
    ProductCategory.create :name => 'Games', ... # Etc.

    # The "down" method takes care of the data because it
    # drops the whole table.

  end

  def self.down
    drop_table "product_categories"
  end
end

在 Rails 2.3.0 上测试,但这也适用于许多早期版本。

【讨论】:

  • 推荐使用seeds.rb。
  • 是的,但仅适用于干净数据库中的初始数据。当您拥有现有数据集时,种子不适合,然后以需要预先将一些新记录加载到数据库中的方式添加或更改功能除了任何现有数据。为此,您可能需要迁移。我还注意到,标准 Rails 种子机制尚无定论! stackoverflow.com/questions/761123/…
  • 更多面向 RoR:create_table :product_categories drop_table :product_categories
【解决方案2】:

您可以为此使用固定装置。这意味着在某个地方有一个 yaml 文件,其中包含您要插入的数据。

这是我在我的一个应用中为此提交的变更集:

db/migrate/004_load_profiles.rb

require 'active_record/fixtures'

class LoadProfiles < ActiveRecord::Migration
  def self.up
    down()

    directory = File.join(File.dirname(__FILE__), "init_data")
    Fixtures.create_fixtures(directory, "profiles")
  end

  def self.down
    Profile.delete_all
  end
end

db/migrate/init_data/profiles.yaml

admin:
 name: Admin
  value: 1
normal:
 name: Normal user
  value: 2

【讨论】:

    【解决方案3】:

    您也可以在种子.rb 文件中定义,例如:

    Grid.create :ref_code => 'one' , :name => 'Grade Única'
    

    运行后:

    rake db:seed
    

    【讨论】:

      【解决方案4】:

      您的迁移可以访问您的所有模型,因此您不应该在迁移中创建类。

      我使用的是最新的 Rails,我可以确认您发布的示例肯定可以工作。

      但是,迁移是一种特殊的野兽。只要你清楚,我看不出ActiveRecord::Base.connection.execute("INSERT INTO product_types (name) VALUES ('type1'), ('type2')") 有什么问题。

      这样做的好处是,您可以通过使用某种 GUI 或 Web 前端来填充您的起始数据,然后执行 mysqldump -uroot database_name.product_types 来轻松生成它。

      对于那些将要执行迁移和维护产品的人来说,任何事情都会变得最简单。

      【讨论】:

        【解决方案5】:

        你真的不应该使用

        ProductType.create
        

        在您的迁移中。

        我也做过类似的,但从长远来看,它们不能保证有效。

        当您运行迁移时,您正在使用的模型类是您运行迁移时的模型类,而不是您创建迁移时的模型类。您必须确保永远不会以阻止迁移运行的方式更改模型。

        你最好运行 SQL,例如:

        [{name: 'Type', ..}, .. ].each do |type|
          execute("INSERT INTO product_types (name) VALUES ('#{type[:name]} .. )
        end
        

        【讨论】:

          猜你喜欢
          • 2019-02-03
          • 1970-01-01
          • 1970-01-01
          • 2015-10-30
          • 2015-09-22
          • 2015-03-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多