Reputation: 3876
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
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
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
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
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