Опасен ли ввод данных с помощью приспособлений в Ruby on Rails
-
13-09-2019 - |
Вопрос
У меня есть устройства с исходными данными, которые должны храниться в моей базе данных (страны, регионы, перевозчики и т.д.).У меня есть задача 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
Я немного обеспокоен, потому что эта задача очищает мою базу данных и загружает исходные данные.Тот факт, что это даже возможно сделать более одного раза на производстве, пугает меня до чертиков.Нормально ли это, и должен ли я просто быть осторожным?Или люди обычно каким-то образом защищают подобную задачу?
Решение
Заполнение данных приборами - крайне плохая идея.
Приспособления не проверяются, и поскольку большинство разработчиков Rails не используют ограничения базы данных, это означает, что вы можете легко вставить неверные или неполные данные в свою производственную базу данных.
Устройства также по умолчанию устанавливают странные идентификаторы первичных ключей, что не обязательно является проблемой, но раздражает при работе.
Для этого есть множество решений.Мой личный фаворит - это задача rake, которая запускает Ruby-скрипт, который просто использует ActiveRecord для вставки записей.Это то, что Rails 3 будет делать с db:seed
, но вы легко можете написать это сами.
Я дополняю это методом, который я добавляю в ActiveRecord::Base под названием create_or_update
.Используя это, я могу запускать начальный скрипт несколько раз, обновляя старые записи вместо того, чтобы генерировать исключение.
Некоторое время назад я написал статью об этих методах под названием Загрузка исходных данных.
Другие советы
Что касается первой части вашего вопроса, да, я бы просто принял некоторые меры предосторожности для запуска подобной задачи в рабочей среде.Я установил подобную защиту в своей задаче начальной загрузки / заполнения:
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
Я создал в этом суть для некоторого контекста.
Что касается второй части вопроса - обычно вы действительно хотите двух вещей:а) очень простое заполнение базы данных и настройка приложения для разработки, и б) загрузка приложения на рабочий сервер (например:вставка пользователя-администратора, создание папок, от которых зависит приложение, и т.д.).
Я бы использовал fixtures для посева при разработке - тогда все члены команды видят одни и те же данные в приложении, и то, что есть в приложении, согласуется с тем, что есть в тестах.(Обычно я заворачиваю rake app:bootstrap
, rake app:seed
rake gems:install
, и т.д. в rake app:install
таким образом, каждый может работать над приложением, просто клонировав репозиторий и выполнив эту единственную задачу.)
Однако я бы никогда не использовал приспособления для заполнения / начальной загрузки на рабочем сервере.Рельсы' db/seed.rb
действительно подходит для этой задачи, но вы, конечно, можете использовать ту же логику в своей собственной rake app:seed
задача, как указывали другие.
Rails 3 решит это за вас, используя начальный файл.rb.
http://github.com/brynary/rails/commit/4932f7b38f72104819022abca0c952ba6f9888cb
Мы разработали ряд лучших практик, которые мы используем для заполнения данных.Мы в значительной степени полагаемся на начальный уровень, и у нас есть некоторые уникальные требования, поскольку нам необходимо создать многопользовательские системы.Вот несколько лучших практик, которые мы использовали:
- Светильники - не лучшее решение, но вы все равно должны хранить свои исходные данные во что-то другое, кроме Ruby.Код Ruby для хранения исходных данных имеет тенденцию повторяться, а хранение данных в анализируемом файле означает, что вы можете написать универсальный код для согласованной обработки исходных данных.
- Если вы собираетесь потенциально обновить начальные данные, используйте столбец маркера с именем что-то вроде
code
чтобы привести ваш файл seeds в соответствие с вашими фактическими данными.Никогда не полагайтесь на согласованность идентификаторов в разных средах. - Подумайте о том, как вы хотите обработать обновление существующих исходных данных.Есть ли какая-либо вероятность того, что пользователи изменили эти данные?Если да, то должны ли вы сохранять информацию пользователя, а не заменять ее исходными данными?
Если вас интересуют некоторые из способов, которыми мы осуществляем посев, мы упаковали их в драгоценный камень под названием Семеноматический.
Как насчет того, чтобы просто удалить задачу с вашего рабочего сервера после заполнения базы данных?
Мне только что пришла в голову интересная идея...
что, если бы вы создали \db\seeds\ и добавили файлы в стиле миграции:
файл: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
Это позволило бы вам запускать миграции и начальные компоненты в порядке, который позволил бы им сосуществовать более мирно.
мысли?