Добавить строки на миграцию - PullRequest
19 голосов
/ 06 января 2009

Я хотел бы знать, какой способ добавления записей в таблицу базы данных в Rails Migration предпочтителен. Я читал в книге Олы Бини (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

Это красиво и чисто, но по какой-то причине не работает на последних версиях рельсов ...

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

Спасибо!

Ответы [ 5 ]

38 голосов
/ 07 марта 2009

Документация по 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, но это должно работать и для многих более ранних версий.

9 голосов
/ 07 января 2009

Вы можете использовать светильники для этого. Это означает наличие файла 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
7 голосов
/ 19 марта 2010

Вы также можете определить в своем файле seed.rb, например:

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

и после запуска:

rake db:seed
3 голосов
/ 07 января 2009

ваши миграции имеют доступ ко всем вашим моделям, поэтому вам не следует создавать класс внутри миграции.

Я использую последние рельсы и могу подтвердить, что приведенный вами пример определенно ДОЛЖЕН работать.

Однако миграции - это особый зверь. Пока вы чисты, я не вижу ничего плохого в ActiveRecord::Base.connection.execute("INSERT INTO product_types (name) VALUES ('type1'), ('type2')").

Преимущество этого заключается в том, что вы можете легко сгенерировать его, используя какой-либо графический интерфейс или веб-интерфейс для заполнения ваших начальных данных, а затем выполнить mysqldump -uroot database_name.product_types.

Что бы ни делало вещи проще для человека, который будет выполнять ваши миграции и обслуживать продукт.

1 голос
/ 12 октября 2017

Вы действительно не должны использовать

ProductType.create

в ваших миграциях.

Я сделал подобное, но в долгосрочной перспективе они не гарантированно работают.

Когда вы запускаете миграцию, класс модели, который вы используете, является классом во время запуска миграции, а не классом, когда вы создали миграцию. Вы должны быть уверены, что никогда не измените свою модель таким образом, чтобы остановить запуск миграции.

Вам лучше запустить SQL, например:

[{name: 'Type', ..}, .. ].each do |type|
  execute("INSERT INTO product_types (name) VALUES ('#{type[:name]} .. )
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...