Опасно ли заполнять данные с помощью приборов в Ruby on Rails? - PullRequest
11 голосов
/ 12 июня 2009

У меня есть приборы с исходными данными, которые должны храниться в моей базе данных (страны, регионы, операторы и т. Д.). У меня есть задача rake db: seed, которая будет заполнять базу данных.

namespace :db do
  desc "Load seed fixtures (from db/fixtures) into the current environment's database." 
  task :seed => :environment do
    require 'active_record/fixtures'

    Dir.glob(RAILS_ROOT + '/db/fixtures/yamls/*.yml').each do |file|
      Fixtures.create_fixtures('db/fixtures/yamls', File.basename(file, '.*'))
    end
  end
end

Я немного обеспокоен, потому что эта задача очищает мою базу данных и загружает исходные данные. Тот факт, что это даже возможно сделать несколько раз на производстве, пугает меня до чертиков. Это нормально и нужно ли быть осторожным? Или люди обычно каким-то образом защищают такую ​​задачу?

Ответы [ 6 ]

18 голосов
/ 14 июня 2009

Посев данных с помощью приборов - очень плохая идея.

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

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

Есть много решений для этого. Мой личный фаворит - грабли, которые запускают скрипт Ruby, который просто использует ActiveRecord для вставки записей Это то, что Rails 3 будет делать с db:seed, но вы можете легко написать это самостоятельно.

Я дополняю это методом, добавляемым в ActiveRecord :: Base, который называется create_or_update. Используя это, я могу запускать начальный скрипт несколько раз, обновляя старые записи, а не выбрасывая исключение.

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

4 голосов
/ 14 июня 2009

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

task :exit_or_continue_in_production? do
  if Rails.env.production?
    puts "!!!WARNING!!! This task will DESTROY " +
         "your production database and RESET all " +
         "application settings"
    puts "Continue? y/n"
    continue = STDIN.gets.chomp
    unless continue == 'y'
      puts "Exiting..."
      exit! 
    end
  end
end

Я создал эту суть для некоторого контекста.

Что касается второй части вопроса - обычно вам действительно нужны две вещи: а) очень легко заполнить базу данных и настроить приложение для разработки, и б) загрузить приложение на рабочий сервер (например: вставить пользователя-администратора, создание папок зависит от приложения и т. д.).

Я бы использовал светильники для посева в разработке - каждый из команды затем видит те же данные в приложении, и то, что в приложении, соответствует тому, что находится в тестах. (Обычно я помещаю rake app:bootstrap, rake app:seed rake gems:install и т. Д. В rake app:install, чтобы каждый мог работать над приложением, просто клонировав репозиторий и выполнив одну эту задачу.)

Однако я бы никогда не использовал приспособления для заполнения / начальной загрузки на производственном сервере. db/seed.rb Rails действительно подходит для этой задачи, но вы, конечно, можете использовать ту же логику в своей собственной задаче rake app:seed, как и другие.

2 голосов
/ 26 апреля 2012

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

  1. Светильники - не лучшее решение, но вы все равно должны хранить исходные данные в чем-то отличном от Ruby. Ruby-код для хранения начальных данных имеет тенденцию становиться повторяющимся, а хранение данных в разбираемом файле означает, что вы можете написать общий код для последовательной обработки ваших начальных значений.
  2. Если вы собираетесь обновить семена, используйте столбец маркера с именем что-то вроде code, чтобы сопоставить файл семян с вашими фактическими данными. Никогда не полагайтесь на то, что идентификаторы согласованы между средами.
  3. Подумайте, как вы хотите справиться с обновлением существующих начальных данных. Есть ли вероятность того, что пользователи изменили эти данные? Если да, то следует ли вам хранить информацию о пользователе, а не заменять ее начальными данными?

Если вас интересуют некоторые способы посева, мы упаковали их в камень под названием SeedOMatic .

2 голосов
/ 12 июня 2009

Rails 3 решит это за вас, используя файл seed.rb.

http://github.com/brynary/rails/commit/4932f7b38f72104819022abca0c952ba6f9888cb

1 голос
/ 07 августа 2009

У меня просто была интересная идея ...

что если вы создали \ db \ seed \ и добавили файлы в стиле миграции:

файл: 200907301234_add_us_states.rb

class AddUsStates < ActiveRecord::Seeds

  def up
    add_to(:states, [
      {:name => 'Wisconsin', :abbreviation => 'WI', :flower => 'someflower'},
      {:name => 'Louisiana', :abbreviation => 'LA', :flower => 'cypress tree'}
      ]
    end
  end

  def down
    remove_from(:states).based_on(:name).with_values('Wisconsin', 'Louisiana', ...)
  end
end

попеременно:

  def up
    State.create!( :name => ... )
  end

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

мысли

1 голос
/ 12 июня 2009

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

...