Vicente Rodríguez

Nov. 3, 2016

Como usar hstore en postgreSQL y rails

En este tutorial usaremos hstore como una forma de almacenar datos en postgres junto con rails, hstore es parecido a los diccionarios, nos permite guardar información con una clave y su valor, podemos tener [:color] = "azul".

El código de la app esta en github.

Creando la app

Para iniciar una app de rails con postgres como base de datos usamos el comando:


rails new psapp --database=postgresql

ahora dentro del proyecto creamos un nuevo modelo:


rails g model Car name color

eso nos generara una archivo de migración, pero antes de correrla necesitamos cambiar unas lineas:


class CreateCars < ActiveRecord::Migration

  def change

    enable_extension "hstore"

    create_table :cars do |t|

      t.string :name

      t.string :color

      t.hstore :user_preferences



      t.timestamps null: false

    end

    add_index :cars, :user_preferences, using: :gin

  end

end

lo primero que hacemos es agregar enable_extension "hstore" esto sirve para habilitar hstore en la base de datos y también agregamos un nuevo campo de tipo hstore que se llame user_preferences, por ultimo agregamos un index a la columna user_preferences para acceder a sus datos de una manera mas fácil.

Creando el controlador

Necesitamos un controlador para el modelo car:


rails g controller cars index show new 

y el archivo lo modificamos de la siguiente manera:


class CarsController < ApplicationController

  def index

    @cars = Car.all

  end



  def show

    @car = Car.find(params[:id])

  end



  def new

    @car = Car.new

  end



  def create

    @car = Car.new(car_params)

    if @car.save

      redirect_to @car

    else

      render :new

    end

  end



  private

    def car_params

      params.require(:car).permit(:name, :color, user_preferences: [:transmission, :doors_num, :wheels])

    end

end

Es un controlador normal, el único cambio es en los parámetros que definimos, en este caso necesitamos indicar como se llama cada valor que pasaremos en el hstore, esta app necesita de transmission, doors_num y wheels, podemos agregar tantos como queramos, de esta manera quedaría el objeto que pasamos desde el formulario:


user_preferences: {

  transmission: "manual",

  doors_num: 4,

  wheels: 21

}

Vistas

Empezaremos creando la vista del formulario:

New


<%= form_for(@car) do |f| %>

  <%= f.label "Nombre:"%>

  <%= f.text_field :name %> <br>

  <%= f.label "Color:"%> 

  <%= f.text_field :color %> <br>

  <%= f.fields_for :user_preferences do |p| %>

    <%= f.label "Transmision:"%>

    <%= p.select :transmission, options_for_select(["Automatica", "Manual"]) %> <br>

    <%= f.label "Numero de puertas:"%>

    <%= p.select :doors_num, options_for_select(["4", "3"]) %> <br>

    <%= f.label "Llantas:"%>

    <%= p.select :wheels, options_for_select(["15", "17"]) %> <br>

  <% end %>

  <%= f.button "crear" %>

<% end %>

El punto importante en esta vista es como construimos la sección que se encarga de ofrecer los datos para mandar al parámetro user_preferences, al tener los input dentro de fields_for todos se enviaran de la manera [:user_preferences][:transmission], [:user_preferences][:doors_num] cumpliendo lo que necesitamos en el controlador.

Show

Para la vista que muestra cada objeto:


<%= @car.name %> <br>

<%= @car.color %> <br>

<% @car.user_preferences.each do |set| %>

  <%= set[0]%>

  <%= set[1]%> <br>

<% end %>

Para acceder al atributo de tipo hstore de un objeto podemos tratarlo como un array y acceder a los datos numéricamente o podemos pasarle el nombre de la llave:


<%= @car.name %> <br>

<%= @car.color %> <br>

<%= @car.user_preferences[:transmission] %> <br>

<%= @car.user_preferences[:door_num] %> 

Terminamos

Hstore puede ser un gran aliando cuando queremos guardar información que tenga relación, como una encuesta o las respuestas de un examen, por defecto no viene activado en postgres por que conlleva un mayor uso de memoria.