Добавить столбец массива в Rails

Как вы объявляете столбец массива в Rails?

Деталь

У меня есть следующая модель

rails generate model User address:text

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

rails generate model User address[]:text 

Как вы объявляете столбец массива в Rails?

Ответ 1

Вы можете использовать следующие шаги

rails g migration add_subjects_to_book subjects:text

И файл миграции:

class AddSubjectsToBook < ActiveRecord::Migration
  def change
    add_column :books, :subjects, :text, array: true, default: []
  end
end

Мы можем проверить это сейчас:

2.1.2 :001 > b = Book.create
   (0.2ms)  BEGIN
  SQL (2.0ms)  INSERT INTO "books" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id"  [["created_at", "2014-10-17 08:21:17.870437"], ["updated_at", "2014-10-17 08:21:17.870437"]]
   (0.5ms)  COMMIT
 => #<Book id: "39abef75-56af-4ad5-8065-6b4d58729ee0", title: nil, created_at: "2014-10-17 08:21:17", updated_at: "2014-10-17 08:21:17", description: {}, metadata: {}, subjects: []>

2.1.2 :002 > b.subjects.class
 => Array

Если вы хотите добавить массив при создании таблицы, вы можете сделать следующее

create_table :products do |t|
  t.string :name, null: false
  t.references :category, null: false
  t.text :tags, array: true, default: []
end

Ответ 2

Если вы используете Postgres, то в этом посте http://blog.plataformatec.com.br/2014/07/rails-4-and-postgresql-arrays/ предлагается использовать параметр array: true в сценарии миграции:

create_table :users do |t|
  # other columns
  t.text : addresses, array: true, default: []
end

Если вы не используете Postgres, этот ответ может быть полезен: Хранение массивов в базе данных: JSON против сериализованного массива

Ответ 3

Примеры с использованием array: true требуют Postgres или какой-либо другой базы данных, способной работать с массивами. Для MySQL используйте универсальную сериализацию, которая позволяет хранить любой столбец произвольного типа.

Миграция базы данных:

create_table :users do |t|
  t.text :addresses, default: [].to_yaml
  ...
end

Класс с атрибутом массива:

class User < ActiveRecord::Migration
  serialize :addresses, Array
end

Используя атрибут:

u = User.new
u.update_attributes addresses: ["123 Evergreen", "246 Main"]

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