0.0
No commit activity in last 3 years
No release in over 3 years
Discriminate class type based on a model field
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

~> 1.13
~> 5.0
~> 10.0

Runtime

>= 4.0.2
 Project Readme

Discriminator

Discriminator is a gem which makes ActiveRecord smart about loading subclasses from the database. To wit, say we have a class with subclasses:

class Buildings::Base
  def property_value
    raise NotImplementedError.new
  end
end

class Buildings::Library
  def property_value
    "low"
  end
end

class Buildings::Stadium
  def property_value
    "high"
  end
end

class Buildings::SecretBase
  def property_value
    "unknown"
  end
end

We might store these in a table, with a building_type field to determine what type of building it is:

Now, if we try to do something like

Buildings::Library.new(building_type: :library).save
Buildings::Stadium.new(building_type: :stadium).save
Buildings::SecretBase.new(building_type: :secret_base).save
Buildings::Base.all.map(&:class)          # => [Buildings::Base, Buildings::Base, Buildings::Base]
Buildings::Base.all.map(&:property_value) # => NotImplementedError!!

...gross. Ideally, we'd like to load up these records from the databases, with their subclasses already applied! With discriminator, if we add a simple line to our building base:

discriminate Buildings, on: :building_type

Then we get back an ActiveRecord::Relation back, with the appropriate subclass already applied.

Buildings::Base.all.map(&:class)          # => [Buildings::Library, Buildings::Stadium, Buildings::SecretBase]
Buildings::Base.all.map(&:property_value) # => ["low", "high", "unknown"]

This can be exceptionally helpful for a Single Table Inheritance situation, or something like Events where there may be a large number of subclasses which could have very different behaviour per subclass.

I made this gem so I could use it in Loomio.

Installation

(NB that this functionality relies on ActiveRecord >= 4.0.2, when discrimiate_class_for_record was introduced)

Add this line to your application's Gemfile:

gem 'discriminator'

And then execute:

$ bundle

Or install it yourself as:

$ gem install discriminator

Usage

Discriminator defines one method: the discriminate method on ActiveRecord::Base

class Buildings::Base
  discriminate Buildings, on: :building_type
end

Setting a default

By default, discriminator falls back to ModuleName::Base, if a subclass cannot be found but this can be be overridden by the default parameter:

class Kickflips::Basic
  discriminate Kickflips, on: :type, default: :basic
end

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/gdpelican/discriminator. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.

License

The gem is available as open source under the terms of the MIT License.