Project

has-meta

0.0
No commit activity in last 3 years
No release in over 3 years
A key/value store solution for Rails apps with bloated tables
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

Runtime

>= 4.2.8
 Project Readme

Has-Meta

A key/value store solution for Rails apps with bloated tables

Build Status

Installation

Add this line to your application's Gemfile:

gem 'has-meta'

And then execute:

$ bundle

Or install it yourself as:

$ gem install has-meta

Then, install migrations:

rake has_meta_engine:install:migrations

Finally, review the migrations and migrate:

rails db:migrate

Usage

Declaring Meta Attributes

Suppose we have a model Part and only a minority of our parts records have the attribute catalog_number populated. We want to move catalog_number to our key/value store.

To create a new meta attribute on an Active Record model, add this line to your model:

has_meta :catalog_number

Or specify multiple meta attributes on the model:

has_meta :catalog_number, :other_attribute

You may also choose to migrate existing data from a table:

$ rake "has_meta_engine:data_mover[parts, catalog_number, integer, catalog_number]"

Once that data is moved generate a migration to remove the column and run the migration:

$ rake generate migration RevmoveCatalogNumberFromParts catalog_number:integer
$ rake db:migrate

And finally, declare the meta attribute in the model

has_meta :catalog_number

Getting and Setting Meta Attributes

Now, we can use normal getters and setters to access the attribute:

new_part = Part.create name: 'Fancy new part'  
new_part.catalog_number = 12345  
new_part.save

new_part.catalog_number  
# => 12345

You can update the attribute any way you would with other attributes managed by Active Record:

new_part.update catalog_number: 67890  
new_part.catalog_number # => 67890  

new_part.attributes = {catalog_number: 12345}  
new_part.catalog_number # => 12345  

Meta attributes may also represent an Active Record model. Perhaps some of our parts may conform to a uniform standard represented by class Standard. Just declare the meta attribute :standard and has-meta will treat the meta attribute as a one-to-one relation if the attribute corresponds to an Active Record model in your app.

has_meta :catalog_number, :standard

Now you can get or set the attribute using either object or the object id as you would with any other attribute:

new_standard = Standard.create name: 'Some great standard'  
new_part.standard = new_standard  
new_part.standard # => #<Standard id: 1, name: "Some great standard">  
new_part.standard_id # => 1  

newer_standard = Standard.create name 'An even better standard'  
new_part.standard.id = newer_standard.id  
new_part.standard # => #<Standard id: 2, name: "An even better standard">  
new_part.standard_id # => 2  

Finding by meta attributes

find_by_attribute_name methods are provided for meta attributes. For attributes representing an Active Record model, use find_by_attribute_id:

Part.find_by_catalog_number 12345  
# => #<Part id: 1, name: "Fancy new part">
    
Part.find_by_standard_id 2  
# => #<Part id: 1, name: "Fancy new part">

You may also use with_meta method to return a scope of parts with correspoding meta attribute values:

another_part = Part.create name: 'Another fancy new part'
another_part.update standard: new_standard

Part.with_meta standard: new_standard
# => #<ActiveRecord::Relation [#<Part id: 1, name: "Fancy new part">, 
    #<Part id: 2, name: "Another fancy new part">]>

with_meta accepts the any: true option to match any condition provided:

yet_another_part = Part.create name: 'Yet another fancy new part'
yet_another_part.update catalog_number: 12345


Part.with_meta({standard: new_standard, catalog_number: 12345}, any: true)
# => #<ActiveRecord::Relation [#<Part id: 1, name: "Fancy new part">, 
  #<Part id: 2, name: "Another fancy new part">, 
  #<Part id: 3, name: "Yet another fancy new part">]>

Calling excluding_meta will return all records not meeting the criteria:

Part.excluding_meta catalog_number: 12345
# => #<ActiveRecord::Relation [#<Part id: 2, name: "Another fancy new part">]>

TODO/Known Issues

has-meta was developed for Active Record 4.2+ and MySQL 5.5. PRs for supporting earlier versions of Active Record and/or PostgreSQL are welcome!

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/protrainings/has-meta.

License

Has-Meta is available as open source under the terms of the MIT License.

About ProTrainings

Has-Meta was written by Dan Drust. It is maintained and funded by Protrainings, LLC. Has-Meta, names, and logos are copyright ProTrainings, LLC.