Rails: Как заполнить Db данными, не мешая миграции? - PullRequest
2 голосов
/ 04 октября 2011

Мое приложение полагается на то, что в базе данных уже есть около 48 000 строк данных (MySql). Мне кажется, что с помощью абстракции ActiveRecord это создаст проблему, заключающуюся в том, что каждый раз, когда происходит миграция, эти данные придется вставлять заново. Это действительно так? Или есть обходной путь?

Ответы [ 2 ]

2 голосов
/ 04 октября 2011

Ruby on Rails обрабатывает миграции, отслеживая изменения, внесенные в схему приложения, дифференцированным образом. Цель этого состоит в том, чтобы предложить очень контролируемый механизм для управления как схемой базы данных, так и данными. Используя миграцию для предварительного заполнения базы данных после создания исходной схемы базы данных, эта миграция будет выполняться только один раз для каждого развертывания приложения.

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

$ rails new example -d mysql
$ cd example/
$ rails generate scaffold Users username:string password:string
  invoke  active_record
  create    db/migrate/20111004022310_create_users.rb
  create    app/models/user.rb
  ...
  ...

Эта миграция создает таблицу users с двумя строковыми полями - именем пользователя и паролем. Довольно просто Теперь, в этом примере, я предполагаю, что вы предварительно сконфигурировали свой database.yml.

Создание базы данных, загрузка схемы и начальные миграции

$ rake db:setup
/Sites/example/db/schema.rb doesn't exist yet. Run 
"rake db:migrate" to create it then try again. If
you do not intend to use a database, you should
instead alter /Sites/example/config/application.rb
to limit the frameworks that will be loaded

Нам все еще нужно объединить начальные миграции в схему. Это загрузит исходную спецификацию модели вашего пользователя в схему базы данных, после чего можно будет настроить базу данных.

$ rake db:migrate
==  CreateUsers: migrating ====================================================
-- create_table(:users)
   -> 0.2389s
==  CreateUsers: migrated (0.2390s) ===========================================
$ rake db:setup
-- create_table("users", {:force=>true})
   -> 0.1460s
-- initialize_schema_migrations_table()
   -> 0.5908s
-- assume_migrated_upto_version(20111004022310, "db/migrate")
   -> 0.0010s

В этот момент вы можете легко перейти в rails console и увидеть начальную конфигурацию.

$ rails console
ruby-1.9.2-p180 :007 > u = User.new(:username => 'test', :password => 'testing?')
 => #<User id: nil, username: "test", password: "testing?", created_at: nil, updated_at: nil> 
ruby-1.9.2-p180 :008 > u.save!
 => true
ruby-1.9.2-p180 :009 > User.all
 => [#<User id: 2, username: "test", password: "testing?", created_at: "2011-10-04 02:33:56", updated_at: "2011-10-04 02:33:56">] 

Предварительное заполнение базы данных

Чтобы вы могли видеть, как выглядит первоначальная миграция пользователей.

$ cat db/migrate/20111004022310_create_users.rb
class CreateUsers < ActiveRecord::Migration
  def self.up
    create_table :users do |t|
      t.string :username
      t.string :password

      t.timestamps
    end
  end

  def self.down
    drop_table :users
  end
end

Чтобы заполнить его, вам нужно будет создать миграцию, которая будет действовать как прокси между вашим предпочтительным интерфейсом данных и ActiveRecord. Если он где-то находится в базе данных, я бы порекомендовал использовать что-то вроде FasterCSV, чтобы импортировать его в раздел self.up (или up) вашей новой миграции. Эта миграция будет выполняться только один раз для каждого развертывания приложения, если вы не удалите базу данных и не начнете заново.

$ rails generate migration prepopulate_users
      invoke  active_record
      create    db/migrate/20111004024648_prepopulate_users.rb
$ cat db/migrate/20111004024648_prepopulate_users.rb 
class PrepopulateUsers < ActiveRecord::Migration
  def self.up
    # Assuming the 'results' is set up as an Enumerable for your data
    results.each do |row|
      u = User.new( :username => row[:username],
                    :password => row[:password] )
      u.save!
    end
  end

  def self.down
  end
end

Слово предостережения

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

Также возможен недосмотр

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

И если я здесь совершенно не в теме, не стесняйтесь комментировать, и я соответствующим образом скорректирую свой ответ.

1 голос
/ 04 октября 2011

В rails миграция - это код, который выполняет (обычно обратимое) изменение схемы вашей базы данных.Примерами миграций являются добавление столбца или столбцов в таблицу, изменение имени столбца или добавление всей таблицы.Это аналогично выполнению команды SQL, которая делает то же самое - она ​​не удаляет таблицу и не создает ее заново.

Наличие данных в базе данных при выполнении миграций на самом деле является довольно нормальным случаем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...