chandradot99
chandradot99

Reputation: 3876

Add an array column in Rails

How do you declare an array column in Rails?

Detail

I have the following model

rails generate model User address:text

but I want a model which can store multiple addresses per user. The following declaration gives me an error

rails generate model User address[]:text 

How do you declare an array column in Rails?

Upvotes: 61

Views: 96701

Answers (4)

dimakura
dimakura

Reputation: 7655

If you are using Postgres, then this post http://blog.plataformatec.com.br/2014/07/rails-4-and-postgresql-arrays/ suggests using array: true option in migration script:

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

In case you are not using Postgres, this answer might be helpful: Storing arrays in database : JSON vs. serialized array

Upvotes: 35

mahemoff
mahemoff

Reputation: 46509

The examples using array: true would require Postgres or some other database capable of an arrays type. For MySQL, use generic serialization, which lets you store any arbitrary type in a column.

Database migration:

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

Class with array attribute:

class User < ApplicationRecord
  serialize :addresses, Array
end

Using the attribute:

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

The usual caveats apply to storing arrays in a database. It goes against the grain of relational databases to do this and will make it hard, slow, or impossible to do things like search for an individual item. However, it can be a fine solution for basic storage until you need to do those things.

Upvotes: 25

shrikant1712
shrikant1712

Reputation: 4446

You can use following steps

rails g migration add_subjects_to_book subjects:text

And the migration file:

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

We can check it now:

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

If you want to add array while creating table you can do as follows

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

Note: array column is supported by PostgreSQL

Upvotes: 111

Rahul2692
Rahul2692

Reputation: 344

If using Rails 5, follow the below steps to add an array of address in user table:

Run below command to generate a model with table,

rails generate model User address:text

The table will get create similar to the given below:

class CreateUser < ActiveRecord::Migration[5.2]
  def change
    create_table :users do |t|
      t.text :address
      t.timestamps
    end
  end
end

Now add serialization for the address in a user model

class User < ApplicationRecord
 serialize :address, Array
end

Thank you.

Upvotes: 5

Related Questions