hydra_attribute is an implementation of EAV pattern for ActiveRecord models.
- ruby >= 1.9.2
- active_record >= 3.1
Add the following line to Gemfile:
gem 'hydra_attribute'
and run bundle install
from your shell.
Then we should generate our migration:
rails generate migration create_hydra_attributes
The content should be:
class CreateHydraAttributeTables < ActiveRecord::Migration
def up
create_hydra_entity :products do |t|
# add here all other columns that should be in the entity table
t.timestamps
end
end
def down
drop_hydra_entity :products
end
end
class CreateHydraAttributeTables < ActiveRecord::Migration
def up
migrate_to_hydra_entity :products
end
def down
rollback_from_hydra_entity :products
end
end
rails generate model Product type:string name:string --migration=false
rake db:migrate
and add use_hydra_attributes
to Product class
class Product < ActiveRecord::Base
use_hydra_attributes
end
Starting from version 0.4.0 use_hydra_attributes
method will be removed.
class Product < ActiveRecord::Base
include HydraAttribute::ActiveRecord
end
Product.hydra_attributes.create(name: 'color', backend_type: 'string', default_value: 'green')
Product.hydra_attributes.create(name: 'title', backend_type: 'string')
Product.hydra_attributes.create(name: 'total', backend_type: 'integer', default_value: 1)
Creating method accepts the following options:
-
name. The required parameter. Allowed any string.
-
backend_type. The required parameter. Allowed one of the following strings:
string
,text
,integer
,float
,boolean
anddatetime
. -
default_value. The optional parameter. Allowed any value. By default is
nil
. -
white_list. The optional parameter. Should be
true
orflase
. By defauls isfalse
. if passwhite_list: true
this attribute will be added to white list and will be allowed for mass-assignment. This parameter is in black list for creation by default so if you want to pass it, you have to pass the roleas: :admin
too.Product.hydra_attributes.create({name: 'title', backend_type: 'string', white_list: true}, as: :admin)
Product.create.attributes
# {"id"=>1, created_at"=>..., "updated_at"=>..., "color"=>"green", "title"=>nil, "total"=>1}
Product.create(color: 'red', title: 'toy').attributes
# {"id"=>1, "created_at"=>..., "updated_at"=>..., "color"=>"red", "title"=>"toy", "total"=>1}
Product.create(title: 'book', total: 2).attributes
# {"id"=>1, "created_at"=>..., "updated_at"=>..., "color"=>"green", "title"=>"book", "total"=>2}
Product.hydra_attributes.create(name: 'price', backend_type: 'float', default_value: 0.0)
Product.create(title: 'car', price: 2.50).attributes
# {"id"=>4, "created_at"=>..., "updated_at"=>..., "color"=>"green", "title"=>"car", "price"=>2.5, "total"=>1}
Product.where(color: 'red').map(&:attributes)
# [{"id"=>2, "created_at"=>..., "updated_at"=>..., "color"=>"red", "title"=>"toy", "price"=>0.0, "total"=>1}]
Product.where(color: 'green', price: nil).map(&:attributes)
# [{"id"=>1, "created_at"=>..., "updated_at"=>..., "color"=>"green", "title"=>nil, "price"=>0.0, "total"=>1},
# {"id"=>3, "created_at"=>..., "updated_at"=>..., "color"=>"green", "title"=>"book", "price"=>0.0, "total"=>2}]
Notice: the attribute price
was added in runtime and records that were created before have not this attribute
so they matched this condition where(price: nil)
Product.order(:color).first.attributes
# {"id"=>1, "created_at"=>..., "updated_at"=>..., "color"=>"green", "title"=>nil, "price"=>0.0, "total"=>1}
Product.order(:color).reverse_order.first.attributes
# {"id"=>2, "created_at"=>..., "updated_at"=>..., "color"=>"red", "title"=>"toy", "price"=>0.0, "total"=>1}
Product.select([:color, :title]).map(&:attributes)
# [{"id"=>1, "color"=>"green", "title"=>nil}, {"id"=>2, "color"=>"red", "title"=>"toy"},
# {"id"=>3, "color"=>"green", "title"=>"book"}, {"id"=>4, "color"=>"green", "title"=>"car"}]
Notice: id
attribute will be added if we want to select hydra attribute
Product.group(:color).count
# {"green"=>3, "red"=>1}
The each new minor version doesn't guarantee back compatibility with previous one until the first major version will be released.
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Added some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request