2011-11-11 11 views
28

¿Es posible crear un atributo para una clase que es una matriz? Intenté leer this pero no saqué mucho provecho de eso. Quiero hacer algo como esto:Atributo de matriz para Ruby Modelo

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

tal que cuando llamo .thearray en una instancia de Arco consigo una matriz que puedo añadir nuevos elementos a.

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

Respuesta

47

crear un modelo con un campo de texto

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

editar su modelo para hacer el campo en serie a una matriz

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

probarlo

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"] 
6

Migración:

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

En el modelo de uso serialize:

class MyModel 
    serialize :thearray, Array 
    ... 
end 

Como dice Marnen en su respuesta, sería bueno saber qué tipo de información que desea almacenar en esa matriz, un atributo serializado puede no ser la mejor opción.

[Advertencia de Marten Veldthuis] Tenga cuidado con el cambio de la matriz serializada. Si cambia directamente como esto:

my_model.thearray = [1,2,3] 

que funciona bien, pero si usted hace esto:

my_model.thearray << 4 

Entonces ActiveRecord no detectará que el valor de theArray ha cambiado. A decir AR ese cambio, lo que necesita hacer esto:

my_model.thearray_will_change! 
my_model.thearray << 4 
+0

Será una serie de cadenas. ¿Serializar es el camino a seguir? – tquarton

+0

@tquarton Casi seguro que no. Ver mi respuesta –

9

Wh Si puede usar una matriz serializada como se sugirió en tokland, rara vez es una buena idea en una base de datos relacional. Tiene tres alternativas superiores:

  • Si la matriz contiene objetos de entidad, probablemente se modele mejor como una relación has_many.
  • Si la matriz es realmente solo una matriz de valores como números, entonces puede colocar cada valor en un campo separado y usar composed_of.
  • Si va a utilizar muchos valores de matriz que no son has_many s, es posible que desee investigar una base de datos que realmente admita campos de matriz. PostgreSQL hace esto (y los campos de matriz son compatibles con las migraciones de Rails 4), pero es posible que desee utilizar una base de datos no SQL como MongoDB o persistencia de objeto como se supone que proporciona MagLev.

Si puede describir su caso de uso, es decir, qué datos tiene en la matriz, podemos tratar de ayudar a determinar cuál es la mejor línea de acción.

+0

Ah, de acuerdo, mi arreglo solo tendrá cuerdas. ¿Qué piensas? – tquarton

+0

¿Qué representa la matriz? ¿Por qué lo tienes en primer lugar? –

+3

Originalmente escribí que no sabía de ninguna base de datos SQL que almacenara matrices o hash de forma nativa. Resulta que Postgres trata ambos tipos de forma nativa, y Rails 4 los admite en migraciones y ActiveRecord. Solo una razón más para usar Postgres. :) –

Cuestiones relacionadas