Utilizando o recurso de arrays do PostgreSQL com Rails 4
05/05/2014O PostgreSQL permite que registros sejam armazenados como arrays multidimensionais com o comprimento variável e esse recurso pode ser utilizado com o Rails 4.
Imagine que em um e-commerce cada produto cadastrado, deve pertencer a uma
categoria, o recurso de arrays deve ser ativo na migration com a opção
array: true
onde por padrão é atribuído um array vazio. Nossa migration
ficaria assim:
class CreateProducts < ActiveRecord::Migration
def change
create_table :products do |t|
t.string :name
t.string :description
t.string :categories, array: true, default: []
t.timestamps
end
end
end
Verificando com o psql podemos ver o tipo []
criado pelo Postgres que indica
que a coluna criada será tratada como um array:
store_development=# \d products
Table "public.products"
id integer not null default nextval('products_id_seq'::regclass)
name character varying(255)
description character varying(255)
categories character varying(255)[] default '{}'::character varying[]
Indexes:
"products_pkey" PRIMARY KEY, btree (id)
No rails console podemos testar o comportamento do que foi gerado:
irb(main)> Product.create(
name: "Book Rails",
categories:["ruby", "rails", "dev"]
)
(0.2ms) BEGIN SQL (0.4ms) INSERT INTO "products"
("categories", "created_at", "name", "updated_at")
VALUES ($1, $2, $3, $4) RETURNING "id"
[["categories", "{\"ruby\",\"rails\",\"dev\"}"],
["created_at", "2014-05-05 18:33:58.031321"],
["name", "Book Rails"],
["updated_at", "2014-05-05 18:33:58.031321"]]
(9.3ms) COMMIT
=> #<Product:0x007f3f00bee498> {
:id => 2,
:name => "Book Rails",
:categories => [
[0] "ruby",
[1] "rails",
[2] "dev"
],
:created_at => Mon, 05 May 2014 15:33:58 BRT -03:00,
:updated_at => Mon, 05 May 2014 15:33:58 BRT -03:00
}
Voltando ao psql vamos ver como os dados foram armazenados na tabela:
store_development=# select * from products;
id | name | categories |
---+------------+------------------+
2 | Book Rails | {ruby,rails,dev} |
(1 row)
As consultas podem ser feitas normalmente com o ActiveRecord, nada muda:
irb(main)> Product.where("'ruby' = ANY (categories)")
Product Load (1.0ms)
SELECT "products" * FROM "products" WHERE ('ruby' = ANY (categories))
ActiveRecord::Relation [
Product id: 2,
name: "Book Rails",
categories: ["ruby", "rails", "dev"],
created_at: "2014-05-05 18:33:58",
updated_at: "2014-05-05 18:33:58"
]
Explore ao máximo os recursos e confira as referências.
Happy Hacking ;)