web-dev-qa-db-fra.com

Attribut de tableau pour le modèle Ruby

Est-il possible de créer un attribut pour une classe qui est un tableau? J'ai essayé de lire ça mais je n'en ai pas tiré grand chose. Je veux faire quelque chose comme ça:

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

de sorte que lorsque j'appelle .thearray sur une instance d'Arch, je reçois un tableau auquel je peux ajouter de nouveaux éléments.

Ruby-1.9.2-p290 :006 > arc = Arch.new
Ruby-1.9.2-p290 :007 > arc.thearray
 => [] 
28
tquarton

Créer un modèle avec un champ de texte

> 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) ==========================================

éditez votre modèle pour que le champ soit sérialisé en tableau

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

le tester

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"] 
48
sorens

Bien que vous puissiez utiliser un tableau sérialisé comme suggéré par tokland, c'est rarement une bonne idée dans une base de données relationnelle. Vous avez trois alternatives supérieures:

  • Si le tableau contient des objets d'entité, il est probablement préférable de le modéliser comme une relation has_many.
  • Si le tableau est vraiment juste un tableau de valeurs telles que des nombres, vous pouvez alors placer chaque valeur dans un champ séparé et utiliser composed_of.
  • Si vous allez utiliser beaucoup de valeurs de tableau qui ne sont pas has_manys, vous pouvez explorer une base de données prenant en charge les champs de tableau. PostgreSQL le fait (les champs de tableau sont pris en charge dans les migrations Rails 4), mais vous pouvez utiliser une base de données non-SQL telle que MongoDB ou une persistance d’objet telle que MagLev est supposée fournir.

Si vous pouvez décrire votre cas d'utilisation (c'est-à-dire les données que vous avez dans le tableau), nous pouvons essayer de vous aider à déterminer le meilleur plan d'action.

10

Migration:

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

Dans le modèle, utilisez sérialisez :

class MyModel
  serialize :thearray, Array
  ...
end

Comme Marnen le dit dans sa réponse, il serait bon de savoir quel type d’informations vous souhaitez stocker dans ce tableau, un attribut sérialisé n’est peut-être pas la meilleure option.

[Avertissement de Marten Veldthuis] Veillez à ne pas modifier le tableau sérialisé. Si vous le changez directement comme ceci:

my_model.thearray = [1,2,3]

Cela fonctionne bien, mais si vous faites ceci:

my_model.thearray << 4

Alors ActiveRecord ne détectera pas que la valeur de l'array a changé. Pour parler à AR de ce changement, vous devez procéder comme suit:

my_model.thearray_will_change!
my_model.thearray << 4
6
tokland

Si vous utilisez Postgres, vous pouvez utiliser sa fonctionnalité Array :

Migration:

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

Et puis utilisez-le simplement comme un tableau:

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

Marnen a mentionné cette approche, mais je crois qu'un exemple serait utile ici.

0
akz92