Array Attribute for Ruby Model Array Attribute for Ruby Model ruby ruby

Array Attribute for Ruby Model


Create a model with a text field

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

edit your model to make the field serialized to an array

class Arches < ActiveRecord::Base  serialize :thearray,Arrayend

test it out

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


While you can use a serialized array as tokland suggested, this is rarely a good idea in a relational database. You have three superior alternatives:

  • If the array holds entity objects, it's probably better modeled as a has_many relationship.
  • If the array is really just an array of values such as numbers, then you might want to put each value in a separate field and use composed_of.
  • If you're going to be using a lot of array values that aren't has_manys, you might want to investigate a DB that actually supports array fields. PostgreSQL does this (and array fields are supported in Rails 4 migrations), but you might want to use either a non-SQL database like MongoDB or object persistence such as MagLev is supposed to provide.

If you can describe your use case -- that is, what data you've got in the array -- we can try to help figure out what the best course of action is.


Migration:

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

In the model use serialize:

class MyModel  serialize :thearray, Array  ...end

As Marnen says in his answer, it would be good to know what kind of info you want to store in that array, a serialized attribute may not be the best option.

[Marten Veldthuis' warning] Be careful about changing the serialized array. If you change it directly like this:

my_model.thearray = [1,2,3]

That works fine, but if you do this:

my_model.thearray << 4

Then ActiveRecord won't detect that the value of thearray has changed. To tell AR about that change, you need to do this:

my_model.thearray_will_change!my_model.thearray << 4