Який найкращий спосіб засіяти базу даних у Rails?


82

У мене є завдання rake, яке заповнює деякі вихідні дані у моєму додатку rails. Наприклад, країни, штати, оператори мобільного зв'язку тощо.

Як я зараз це налаштовую, я маю купу операторів створення у файлах у / 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"

Ідея тут полягає в тому, що я хочу встановити деякі теми для акцій, з яких користувачі починають. У мене проблема з цим методом.

Встановлення ідентифікатора не працює. Це означає, що якщо я вирішу додати тему, назвемо її "червоною", тоді я просто хотів би додати заяву теми до цього файлу приладу і викликати завдання rake для повторного завантаження бази даних. Якщо я це зроблю, оскільки теми належать іншим об’єктам та їх ідентифікатор змінюється при цій повторній ініціалізації, усі посилання порушуються.

Моє питання насамперед, чи це хороший спосіб впоратись із засіванням бази даних? У попередньому дописі це мені рекомендували.

Якщо так, то як я можу жорстко кодувати ідентифікатори, і чи є у цього мінуси?

Якщо ні, то який найкращий спосіб залучити базу даних?

Я по-справжньому оціню довгі та продумані відповіді, що включають найкращі практики.

Відповіді:


113

Оновлення, оскільки ці відповіді трохи застаріли (хоча деякі все ще застосовуються).

Проста функція, додана в reils 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

Зазвичай потрібні 2 типи даних про насіння.

  • Основні дані, на які може покладатися ядро ​​вашої програми. Я називаю це звичайним насінням.
  • Дані про навколишнє середовище , наприклад, для розробки програми корисно мати купу даних у відомому стані, які ми можемо використовувати для роботи над додатком локально (відповідь 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')

При використанні з фейкером він може дуже швидко заповнити базу даних асоціаціями, не маючи балаканини з Fixture (юк).

У мене є такий код у завданні граблі.

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

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

2
Використовувати FactoryGirl для насіння не рекомендується, перегляньте цей пост .
blackbiron

26

Використовувати seeds.rbфайл or 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 має вбудований спосіб насіння даних, як пояснено тут .

Іншим способом було б використовувати самоцвіт для більш просунутих або легких посівів, таких як: насіннєвий банк .

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

Додавання актуальної відповіді, оскільки ця відповідь була вперше в Google.


-3

Найкращий спосіб - використовувати світильники.

Примітка: Майте на увазі, що світильники виконують прямі вставки і не використовують вашу модель, тому, якщо у вас є зворотні виклики, які заповнюють дані, вам потрібно буде знайти обхідний шлях.


-4

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


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

c = Category.create (stuff) p = Post.create (stuff) p.category = c Не потрібно чітко встановлювати ідентифікатори. Якщо ви зміните початкові дані, ви просто створите нову міграцію. Досить просто.
Метт Рогіш,

тобто припускаючи, що асоціації можуть бути створені під час створення об’єкта. ось приклад, коли я вважаю, що ваша логіка зазнає невдачі ... виправте мене, якщо я помиляюся. я засіваю БД темами шаблонів. user id = 1 створює шаблон id = 2 і з темою id = 4. на цей момент запис знаходиться в базі даних наступним чином: template: id = 2, user_id = 1, theme_id = 4. тепер, якщо я повторно ініціюю db, тема id = 4 тепер є темою id = 10 ... і тоді шаблон користувача неправильно тематизований
Тоні,

ну, це залежить від того, що ви маєте на увазі під "повторним запуском" - якщо ви починаєте з нуля, Rails обробляє всі асоціації автоматично. Якщо ви важко кодуєте значення ідентифікатора (погано !!!), тоді так, це підірветься.
Метт Рогіш,

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