Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Implementation of EAV pattern for ActiveRecord models
Ruby

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.
features
gemfiles
lib
spec
.gitignore
.rspec
.travis.yml
Appraisals
CHANGELOG.md
Gemfile
LICENSE
README.md
Rakefile
hydra_attribute.gemspec

README.md

hydra_attribute

Build Status

hydra_attribute is an implementation of EAV pattern for ActiveRecord models.

Requirements

  • ruby >= 1.9.2
  • active_record >= 3.1

Installation

Add the following line to Gemfile:

gem 'hydra_attribute'

and run bundle install from your shell.

After successful installation run rails generator:

rails generate hydra_attribute:install

This command generates hydra_attribute initializer:

HydraAttribute.setup do |config|
  # Add prefix for all attribute tables
  # config.table_prefix = 'hydra_'

  # Add prefix for has_many associations
  # config.association_prefix = 'hydra_'

  # Wrap all associated models in HydraAttribute module
  # config.use_module_for_associated_models = true
end

And the last step is to generate db:migration:

rails generate migration create_hydra_attrubute_tables

Migration should look like this:

class CreateHydraAttributeTables < ActiveRecord::Migration
  def up
    HydraAttribute::Migration.new(self).migrate
  end

  def down
    HydraAttribute::Migration.new(self).rollback
  end
end

Usage

Generate model
rails generate model Product type:string name:string
rails generate model SimpleProduct --migration=false --parent=Product
rake db:migrate
Describe EAV attributes
class SimpleProduct < Product
  attr_accessible :name, :title, :code, :quantity, :price, :active, :description

  define_hydra_attributes do
    string  :title, :code
    integer :quantity
    float   :price
    boolean :active
    text    :description
  end
end
Create some products
SimpleProduct.create(name: 'Book', title: 'book', code: '100', quantity: 5, price: 2.75, active: true,  description: '...')
SimpleProduct.create(name: 'Book', title: 'book', code: '101', quantity: 5, price: 3.75, active: true,  description: '...')
SimpleProduct.create(name: 'Book', title: 'book', code: '102', quantity: 4, price: 4.50, active: false, description: '...')
SimpleProduct.create(name: 'Book', title: nil,    code: '103', quantity: 3, price: 4.50, active: true,  description: '...')
SimpleProduct.create(name: 'Book',                code: '104', quantity: 2, price: 5.00, active: true,  description: '...')
"where"
SimpleProduct.where(name: 'Book', quantity: 5, price: 2.75).first.attributes
=> {"id"=>1, "type"=>"SimpleProduct", "name"=>"Book", "created_at"=>Tue, 05 Jun 2012 23:13:21 UTC +00:00, "updated_at"=>Tue, 05 Jun 2012 23:13:21 UTC +00:00, "title"=>"book", "code"=>"100", "quantity"=>5, "price"=>2.75, "active"=>true, "description"=>"..."} 

SimpleProduct.where(title: 'book', active: false).first.attributes
=> {"id"=>3, "type"=>"SimpleProduct", "name"=>"Book", "created_at"=>Tue, 05 Jun 2012 23:13:50 UTC +00:00, "updated_at"=>Tue, 05 Jun 2012 23:13:50 UTC +00:00, "title"=>"book", "code"=>"102", "quantity"=>4, "price"=>4.5, "active"=>false, "description"=>"..."}

SimpleProduct.where(title: nil).first.attributes
=> {"id"=>4, "type"=>"SimpleProduct", "name"=>"Book", "created_at"=>Tue, 05 Jun 2012 23:13:50 UTC +00:00, "updated_at"=>Tue, 05 Jun 2012 23:13:50 UTC +00:00, "title"=>nil, "code"=>"103", "quantity"=>3, "price"=>4.5, "active"=>true, "description"=>"..."} 

SimpleProduct.where(title: nil).last.attributes
=> {"id"=>5, "type"=>"SimpleProduct", "name"=>"Book", "created_at"=>Tue, 05 Jun 2012 23:13:51 UTC +00:00, "updated_at"=>Tue, 05 Jun 2012 23:13:51 UTC +00:00, "title"=>nil, "code"=>"104", "quantity"=>2, "price"=>5.0, "active"=>true, "description"=>"..."}
"order" and "reverse_order"
SimpleProduct.order(:code).first.attributes
=> {"id"=>1, "type"=>"SimpleProduct", "name"=>"Book", "created_at"=>Tue, 05 Jun 2012 23:30:48 UTC +00:00, "updated_at"=>Tue, 05 Jun 2012 23:30:49 UTC +00:00, "title"=>"book", "code"=>"100", "quantity"=>5, "price"=>2.75, "active"=>true, "description"=>"..."} 

SimpleProduct.order(:code).reverse_order.first.attributes
=> {"id"=>5, "type"=>"SimpleProduct", "name"=>"Book", "created_at"=>Tue, 05 Jun 2012 23:30:51 UTC +00:00, "updated_at"=>Tue, 05 Jun 2012 23:30:51 UTC +00:00, "title"=>nil, "code"=>"104", "quantity"=>2, "price"=>5.0, "active"=>true, "description"=>"..."} 
"select"
SimpleProduct.select([:code, :price]).map(&:attributes)
=> [{"code"=>"100", "price"=>2.75}, {"code"=>"101", "price"=>3.75}, {"code"=>"102", "price"=>4.5}, {"code"=>"103", "price"=>4.5}, {"code"=>"104", "price"=>5.0}]

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Added some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request
Something went wrong with that request. Please try again.