LookupBy
Description
LookupBy is a thread-safe lookup table cache for ActiveRecord that reduces normalization pains.
Features
- Thread-safety
- Configurable lookup column
- Caching (read-through, write-through, Least Recently Used (LRU))
Compatibility
- PostgreSQL
Development
Source
- git clone git://github.com/companygardener/lookup_by.git
Issues
Please submit issues to this Github project in the Issues tab. Provide a failing rspec test that works with the existing test suite.
Installation
# in Gemfile
gem "lookup_by"
$ bundle
Or install it manually:
$ gem install lookup_by
Usage / Configuration
ActiveRecord Plugin
LookupBy adds 2 macro methods to ActiveRecord::Base
lookup_by :column_name
# Defines .[], .lookup, and .is_a_lookup? class methods.
lookup_for :column_name
# Defines #column_name and #column_name= accessors that transparently reference the lookup table.
Define the lookup model
# db/migrate/201301010012_create_statuses_table.rb
create_table :statuses do |t|
t.string :status, null: false
end
# app/models/status.rb
class Status < ActiveRecord::Base
lookup_by :status # Replace :status with the name of your lookup column
end
# Aliases the lookup attribute to :name.
Status.new(name: "paid")
Associations / Foreign Keys
# db/migrate/201301010123_create_orders_table.rb
create_table :orders do |t|
t.belongs_to :status
end
# app/models/order.rb
class Order < ActiveRecord::Base
lookup_for :status
end
Creates accessors to use the status attribute transparently:
order = Order.new(status: "paid")
order.status
=> "paid"
# Access the lookup object
order.raw_status
=> <#Status id: 1, status: "paid">
# Access the lookup value before type casting
order.status_before_type_cast
=> "paid"
Symbolize
Casts the attribute to a symbol. Enables the setter to take a symbol.
This is a bad idea if the set of lookup values is large. Symbols are never garbage collected.
class Order < ActiveRecord::Base
lookup_for :status, symbolize: true
end
order = Order.new(status: "paid")
order.status
=> :paid
order.status = :shipped
=> :shipped
Strict
Do you want missing lookup values to raise an error?
# Raise
# Default
lookup_for :status
# this will raise a LookupBy::Error
Order.status = "non-existent status"
# Set to nil
lookup_for :status, strict: false
Caching
# No caching - Not very useful
# Default
lookup_by :column_name
# Cache all
# Use for a small finite list (e.g. status codes, US states)
#
# find: false DEFAULT
lookup_by :column_name, cache: true
# Cache N (with LRU eviction)
# Use for a large list with uneven distribution (e.g. email domain, city)
#
# find: true DEFAULT and REQUIRED
lookup_by :column_name, cache: 50
Configure cache misses
# Return nil
# Default when caching all records
#
# Skips the database for these methods:
# .all, .count, .pluck
lookup_by :column_name, cache: true
# Find (read-through)
# Required when caching N records
lookup_by :column_name, cache: 10
lookup_by :column_name, cache: true, find: true
Configure database misses
# Return nil
# Default
lookup_by :column_name
# Find or create
# Useful for user-submitted fields that grow over time
# e.g. user_agents, ip_addresses
#
# Note: Only works if attributes are nullable
lookup_by :column_name, cache: 20, find_or_create: true
Normalizing values
# Normalize
# Run through the your attribute's setter
lookup_by :column_name, normalize: true
Integration
Cucumber
# features/support/env.rb
require 'lookup_by/cucumber'
This provides: Given I reload the cache for $plural_class_name
SimpleForm
= simple_form_for @order do |f|
= f.input :status
= f.input :status, :as => :radio_buttons
Formtastic
= semantic_form_for @order do |f|
= f.input :status
= f.input :status, :as => :radio
Testing
This plugin uses rspec and pry for testing. Make sure you have them installed:
bundle
To run the test suite:
rake
Giving Back
Contributing
- Fork
- Create a feature branch
git checkout -b new-hotness - Commit your changes
git commit -am 'Added some feature' - Push to the branch
git push origin new-hotness - Create a Pull Request
Attribution
A list of authors can be found on the LookupBy Contributors page.
Copyright © 2012 Erik Peterson, Enova
Released under the MIT License. See MIT-LICENSE file for more details.

