Last Updated: February 25, 2016
·
2.854K
· stereoscott

Using PostgreSQL's hstore with Rails 4: boolean properties, too!

Rails 4 supports a few native PostgreSQL types including hstore.

With a little bit of meta-programming you can really soup up your models to store various properties without having to run database migrations. Here are my two favorite techniques. The first allows you to check and set boolean properties, the second is general purpose. You also get scopes like has_xxx('value') which is useful when querying your data.

Boolean Properties

%w[display_redemption_code display_order_number].each do |key|
  scope "has_#{key}", ->(value) { where("properties @> hstore(?, ?)", key, value) }

  define_method("#{key}?") do
    if properties && properties[key].present? then 
      ActiveRecord::ConnectionAdapters::Column.value_to_boolean(properties[key]) 
    else 
      nil
    end
  end

  alias_method "#{key}".to_sym, "#{key}?".to_sym 

  define_method("#{key}=") do |value|
    self.properties = (properties || {}).merge(key => value)
  end
end

Other Property Types

%w[products_title].each do |key|
  scope "has_#{key}", ->(value) { where("properties @> hstore(?, ?)", key, value) }

  define_method(key) do
    properties && properties[key]
  end

  define_method("#{key}=") do |value|
    self.properties = (properties || {}).merge(key => value)
  end
end    

More details on how to enable hstore: http://platformonrails.wordpress.com/2013/03/17/enabling-postgresql-hstore-with-rails-4/