Який найкращий спосіб засіяти базу даних у 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.