Deprecated
This gem is no longer maintained and the repository is archived. It was written for Rails 3 and 4.0 and is not tested against anything newer. Modern Rails covers its use cases with built-in features:
Sparse or optional attributes
If you reached for has_meta_data to avoid wide tables full of mostly-NULL columns, consider:
-
Nullable columns. PostgreSQL and MySQL store NULLs very cheaply; a mostly-empty column usually costs little.
-
A JSON/JSONB column with
store_accessor. Keeps the data on the same row, needs no extra query or JOIN, and can be indexed and queried directly. The store_model or jsonb_accessor gems add typed attributes on top.
For example, with a metadata JSON column on articles:
class Article < ApplicationRecord store_accessor :metadata, :reference_link, :reference_note end
Class Table Inheritance
If you used it alongside STI to approximate Class Table Inheritance, use delegated_type (Rails 6.1+).
Keeping a separate meta table
If you really do want the data in a second table, plain Rails (7.0+) does what this gem did in a few lines:
class Article < ApplicationRecord has_one :meta, class_name: "ArticleMeta", autosave: true, dependent: :destroy scope :with_meta, -> { where.associated(:meta) } scope :without_meta, -> { where.missing(:meta) } META_ATTRIBUTES = %i[reference_link reference_note] delegate(*META_ATTRIBUTES, to: :meta, allow_nil: true) META_ATTRIBUTES.each do |attr| define_method("#{attr}=") { |value| (meta || build_meta).public_send("#{attr}=", value) } end end
The original documentation is preserved below for reference.
Has Meta Data
This plugin allows you to extend one of your models with additional supplementary data stored in another table through a has_one relationship. The benefit of this plugin over a simple has_one is that the meta model class is dynamically defined (though extendable via the has_meta_data declaration) and fields on the meta model are automatically delegated to from the main model, allowing you to work solely with your primary model and not worry about the storage of the data in a separate meta table. This plugin also automatically handles creation of the meta model if you set a field on your model that exists in the meta model table.
Common use cases for this are database efficiency if only a small number of your records have a certain set of data or in conjunction with STI to accomplish something akin to Class Table Inheritance (CTI).
In short, it’s a transparent way of splitting up data into two tables while still treating them as one model.
Installation
This gem works with Rails 3 only.
In your Gemfile:
gem "has_meta_data"
Basic Example
## Database Schema create_table :articles, :force => true do |t| t.string :title t.text :body end create_table :article_meta, :force => true do |t| t.references :article t.string :reference_link t.text :reference_note end ## Model class Article < ActiveRecord::Base has_meta_data end ## Exposed Class Methods & Scopes: Article.meta_data_class => Article::Meta Article.with_meta_data.all => (Articles that have associated meta data) Article.without_meta_data.all => (Articles with no associated meta data) ## Usage Examples: article = Article.create(:title => 'Title', :body => 'Body') article.has_meta_data? # => false article.reference_link = 'http://benhughes.name/' article.has_meta_data? # => true article.meta # => #<Article::Meta reference_link: "http://benhughes.name/", reference_note: nil> article = Article.create(:title => 'Title', :body => 'Body', :reference_link => 'http://benhughes.name/') article.has_meta_data? # => true article.reference_link # => "http://benhughes.name/"
Changing the Defaults
You can control the name of the meta class, foreign key, and table name not unlike ActiveRecord associations:
class Article < ActiveRecord::Base has_meta_data :class_name => 'AdditionalData', :foreign_key => 'news_article_id', :table_name => 'news_article_additional_data' end
Extending the Meta Data Class
Because you don’t directly define the meta data class, you can specify a block of code to be run in its context by passing a block to has_draft:
class Article < ActiveRecord::Base belongs_to :user has_meta_data do belongs_to :some_author def do_something # Something end end end
Running Tests
This gem uses appraisal to test with different versions of the dependencies. See Appraisal first for which versions are tested.
# Just the gems locked in Gemfile.lock $ bundle exec rake test # All of the Appraisals: $ bundle exec rake all