Подтвердить что ты не робот

Атрибут массива для модели Ruby

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

class CreateArches < ActiveRecord::Migration
  def change
    create_table :arches do |t|
      t.string :name
      t.array :thearray
      t.timestamps
    end
  end
end

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

ruby-1.9.2-p290 :006 > arc = Arch.new
ruby-1.9.2-p290 :007 > arc.thearray
 => [] 
4b9b3361

Ответ 1

Создайте модель с текстовым полем

> rails g model Arches thearray:text
  invoke  active_record
  create    db/migrate/20111111174052_create_arches.rb
  create    app/models/arches.rb
  invoke    test_unit
  create      test/unit/arches_test.rb
  create      test/fixtures/arches.yml
> rake db:migrate
==  CreateArches: migrating ===================================================
-- create_table(:arches)
   -> 0.0012s
==  CreateArches: migrated (0.0013s) ==========================================

отредактируйте свою модель, чтобы сериализовать поле в массив

class Arches < ActiveRecord::Base
  serialize :thearray,Array
end

проверить его

ruby-1.8.7-p299 :001 > a = Arches.new
 => #<Arches id: nil, thearray: [], created_at: nil, updated_at: nil> 
ruby-1.8.7-p299 :002 > a.thearray
 => [] 
ruby-1.8.7-p299 :003 > a.thearray << "test"
 => ["test"] 

Ответ 2

Хотя вы можете использовать сериализованный массив как предлагаемый tokland, это редко бывает хорошей идеей в реляционной базе данных. У вас есть три превосходные альтернативы:

  • Если массив содержит объекты сущности, он, вероятно, лучше моделируется как отношение has_many.
  • Если массив действительно представляет собой массив значений, таких как числа, тогда вы можете поместить каждое значение в отдельное поле и использовать composed_of.
  • Если вы собираетесь использовать множество значений массива, которые не являются has_many s, вам может понадобиться изучить БД, которая фактически поддерживает поля массива. PostgreSQL делает это (и поля массива поддерживаются при миграции Rails 4), но вы можете использовать либо базу данных, отличную от SQL, например MongoDB, либо сохранение объекта, например MagLev должен предоставить.

Если вы можете описать свой случай использования - то есть какие данные у вас есть в массиве - мы можем попытаться выяснить, что такое лучший способ действий.

Ответ 3

Миграция:

t.text :thearray, :default => [].to_yaml

В модели используйте serialize:

class MyModel
  serialize :thearray, Array
  ...
end

Как говорит Марнен в своем ответе, было бы хорошо знать, какую информацию вы хотите сохранить в этом массиве, сериализованный атрибут может быть не лучшим вариантом.

[Предупреждение Marten Veldthuis] Будьте осторожны с изменением сериализованного массива. Если вы измените его прямо следующим образом:

my_model.thearray = [1,2,3]

Это работает отлично, но если вы это сделаете:

my_model.thearray << 4

Затем ActiveRecord не обнаружит, что значение thearray изменилось. Чтобы сообщить AR об этом изменении, вам нужно сделать следующее:

my_model.thearray_will_change!
my_model.thearray << 4

Ответ 4

Если вы используете Postgres, вы можете использовать его функцию Array:

Миграция:

add_column :model, :attribute, :text, array: true, default: []

А затем просто используйте его как массив:

model.attribute # []
model.attribute = ["d"] #["d"]
model.attribute << "e" # ["d", "e"]

Этот подход был упомянут Марненом, но я думаю, что пример будет полезен здесь.