Как лучше всего засеять базу данных в Rails?


82

У меня есть задача rake, которая заполняет некоторые исходные данные в моем приложении rails. Например, страны, штаты, операторы мобильной связи и т. Д.

Теперь у меня есть несколько операторов create в файлах в / db / fixtures и задача rake, которая их обрабатывает. Например, у меня есть одна модель - это темы. У меня есть файл theme.rb в / db / fixtures, который выглядит так:

Theme.delete_all
Theme.create(:id => 1, :name=>'Lite', :background_color=>'0xC7FFD5', :title_text_color=>'0x222222',
                      :component_theme_color=>'0x001277', :carrier_select_color=>'0x7683FF', :label_text_color=>'0x000000',
                      :join_upper_gradient=>'0x6FAEFF', :join_lower_gradient=>'0x000000', :join_text_color=>'0xFFFFFF',
                      :cancel_link_color=>'0x001277', :border_color=>'0x888888', :carrier_text_color=>'0x000000', :public => true)

Theme.create(:id => 2, :name=>'Metallic', :background_color=>'0x000000', :title_text_color=>'0x7299FF',
                      :component_theme_color=>'0xDBF2FF', :carrier_select_color=>'0x000000', :label_text_color=>'0xDBF2FF',
                      :join_upper_gradient=>'0x2B25FF', :join_lower_gradient=>'0xBEFFAC', :join_text_color=>'0x000000',
                      :cancel_link_color=>'0xFF7C12', :border_color=>'0x000000', :carrier_text_color=>'0x000000', :public => true)

Theme.create(:id => 3, :name=>'Blues', :background_color=>'0x0060EC', :title_text_color=>'0x000374',
                      :component_theme_color=>'0x000374', :carrier_select_color=>'0x4357FF', :label_text_color=>'0x000000',
                      :join_upper_gradient=>'0x4357FF', :join_lower_gradient=>'0xffffff', :join_text_color=>'0x000000',
                      :cancel_link_color=>'0xffffff', :border_color=>'0x666666', :carrier_text_color=>'0x000000', :public => true)
puts "Success: Theme data loaded"

Идея здесь в том, что я хочу установить для пользователей несколько стандартных тем. У меня проблема с этим методом.

Установить ID не получается. Это означает, что если я решу добавить тему, назовем ее «Красная», тогда я просто хотел бы добавить оператор темы в этот файл фикстуры и вызвать задачу rake для повторного заполнения базы данных. Если я это сделаю, потому что темы принадлежат другим объектам и их идентификатор изменится при повторной инициализации, все ссылки будут разорваны.

Мой вопрос в первую очередь, это хороший способ обработать заполнение базы данных? В предыдущем посте мне это рекомендовали.

Если да, то как я могу жестко закодировать идентификаторы и есть ли у этого недостатки?

Если нет, то как лучше всего заполнить базу данных?

Я буду искренне признателен за длинные и продуманные ответы, включающие лучшие практики.

Ответы:


113

Обновление, поскольку эти ответы немного устарели (хотя некоторые все еще применимы).

Простая функция добавлена ​​в rails 2.3.4, db / seed.rb

Предоставляет новую задачу по рейку

rake db:seed

Подходит для заполнения общих статических записей, таких как состояния, страны и т. Д.

http://railscasts.com/episodes/179-seed-data

* Обратите внимание, что вы можете использовать фикстуры, если вы уже создали их, чтобы также заполнить задачу db: seed, поместив следующее в свой файл seed.rb (из эпизода railscast):

require 'active_record/fixtures'
Fixtures.create_fixtures("#{Rails.root}/test/fixtures", "operating_systems")

Для Rails 3.x используйте ActiveRecord :: Fixtures вместо константы Fixtures.

require 'active_record/fixtures'
ActiveRecord::Fixtures.create_fixtures("#{Rails.root}/test/fixtures", "fixtures_file_name")

28

Обычно требуются два типа исходных данных.

  • Основные данные, на которые может полагаться ядро ​​вашего приложения. Я называю это обычными семенами.
  • Данные об окружающей среде , например, для разработки приложения полезно иметь набор данных в известном состоянии, которые мы можем использовать для работы с приложением локально (ответ Factory Girl выше касается такого рода данных).

По моему опыту, я всегда сталкивался с необходимостью в этих двух типах данных. Итак, я собрал небольшой драгоценный камень, который расширяет семена Rails и позволяет вам добавлять несколько общих файлов семян в db / seed / и любые исходные данные окружающей среды в db / seed / ENV, например, db / seed / development.

Я обнаружил, что этого подхода достаточно, чтобы дать моим исходным данным некоторую структуру и дать мне возможность настроить мою среду разработки или промежуточную среду в известном состоянии, просто запустив:

rake db:setup

Крепления хрупкие и неудобные в обслуживании, как и обычные свалки sql.


Мне нравятся термины «системные данные» и «данные времени выполнения» для описания вещей, которые код полагается на существующие и данные пользователей. Иногда грань между ними размыта.
— Тим Абелл

27

factory_bot звучит так, как будто он сделает то, чего вы пытаетесь достичь. Вы можете определить все общие атрибуты в определении по умолчанию, а затем переопределить их во время создания. Вы также можете передать фабрике идентификатор:

Factory.define :theme do |t|
  t.background_color '0x000000'
  t.title_text_color '0x000000',
  t.component_theme_color '0x000000'
  t.carrier_select_color '0x000000'
  t.label_text_color '0x000000',
  t.join_upper_gradient '0x000000'
  t.join_lower_gradient '0x000000'
  t.join_text_color '0x000000',
  t.cancel_link_color '0x000000'
  t.border_color '0x000000'
  t.carrier_text_color '0x000000'
  t.public true
end

Factory(:theme, :id => 1, :name => "Lite", :background_color => '0xC7FFD5')
Factory(:theme, :id => 2, :name => "Metallic", :background_color => '0xC7FFD5')
Factory(:theme, :id => 3, :name => "Blues", :background_color => '0x0060EC')

При использовании с faker он может очень быстро заполнить базу данных ассоциациями без необходимости возиться с Fixtures (фу).

У меня есть такой код в грабельной задаче.

100.times do
    Factory(:company, :address => Factory(:address), :employees => [Factory(:employee)])
end

11
FactoryGirl на самом деле предназначена для тестирования вместо приспособлений, но ее также можно использовать для загрузки материалов в производство. Используйте задачу rake, которая имеет db: migrate в качестве предварительного условия для загрузки всех данных по умолчанию. Возможно, вам потребуется сделать задачу сгребания достаточно интеллектуальной, чтобы она не создавала копии существующих данных.
— Боб Аман,

2
Не рекомендуется использовать FactoryGirl для семян, проверьте этот пост .
— blackbiron

26

Использование seeds.rbfile или FactoryBotотлично, но они, соответственно, отлично подходят для фиксированных структур данных и тестирования.

seedbankКамень может дать вам больше контроля и модульность для ваших семян. Он вставляет задачи с граблями, и вы также можете определять зависимости между вашими сидами. В ваш список задач по рейку будут добавлены следующие элементы (например):

rake db:seed                    # Load the seed data from db/seeds.rb, db/seeds/*.seeds.rb and db/seeds/ENVIRONMENT/*.seeds.rb. ENVIRONMENT is the current environment in Rails.env.
rake db:seed:bar                # Load the seed data from db/seeds/bar.seeds.rb
rake db:seed:common             # Load the seed data from db/seeds.rb and db/seeds/*.seeds.rb.
rake db:seed:development        # Load the seed data from db/seeds.rb, db/seeds/*.seeds.rb and db/seeds/development/*.seeds.rb.
rake db:seed:development:users  # Load the seed data from db/seeds/development/users.seeds.rb
rake db:seed:foo                # Load the seed data from db/seeds/foo.seeds.rb
rake db:seed:original           # Load the seed data from db/seeds.rb

1

В Rails есть встроенный способ заполнения данных, как описано здесь .

Другой способ - использовать драгоценный камень для более сложного или простого посева, например: seedbank .

Основное преимущество этого гема и причина, по которой я его использую, заключается в том, что он имеет расширенные возможности, такие как зависимости загрузки данных и начальные данные для каждой среды.

Добавление актуального ответа, так как этот ответ был первым в Google.


-3

Лучше всего использовать приспособления.

Примечание: имейте в виду, что фикстуры выполняют прямые вставки и не используют вашу модель, поэтому, если у вас есть обратные вызовы, которые заполняют данные, вам нужно будет найти обходной путь.


-4

Добавьте его в миграции базы данных, чтобы все получали его по мере обновления. Обрабатывайте всю свою логику в коде ruby ​​/ rails, поэтому вам никогда не придется связываться с явными настройками идентификатора.


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

c = Category.create (материал) p = Post.create (материал) p.category = c Нет необходимости явно устанавливать идентификаторы. Если вы измените исходные данные, вы просто создадите новую миграцию. Очень легко.
— Мэтт Рогиш

это предполагает, что ассоциации могут быть созданы во время создания объекта. вот пример, когда я считаю, что ваша логика не работает ... поправьте меня, если я ошибаюсь. Я заполняю БД шаблонными темами. user id = 1 создает шаблон с id = 2 и с идентификатором темы = 4. в этот момент в базе данных находится следующая запись: template: id = 2, user_id = 1, theme_id = 4. теперь, если я повторно инициализирую базу данных, идентификатор темы = 4 теперь является идентификатором темы = 10 ... а затем шаблон пользователя неверно тематический
— Тони

ну, это зависит от того, что вы подразумеваете под «повторной инициализацией» - если вы начнете с нуля, Rails обработает все ассоциации автоматически. Если вы жестко кодируете значения ID (плохо !!!), тогда да, это взорвется.
— Мэтт Рогиш

хорошо, я начинаю понимать вашу точку зрения, но я должен запустить этот сценарий вами. Я заполняю базу данных таблицей поиска стран. США => id страны = 1. затем пользователь создает ресторан, который существует в США. в строке базы данных ресторанов указано country_id = 1. это очень часто, не так ли? Позже я решаю, что хочу добавить больше стран ... если я очищу базу данных и заново заполню таблицу поиска страны, теперь страна ресторанов больше не точна, если идентификатор не тот же. как мне с этим справиться?
— Тони
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.