Created
June 12, 2018 02:34
-
-
Save twolfson/8e981af620c51d149e92054ea92fa89f to your computer and use it in GitHub Desktop.
Rails acts-as-keyed updated/simplified
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Largely based on `acts-as-keyed` but with less magic (namely make `to_param` consistent, don't overwrite `find`) | |
# https://github.com/jhubert/acts-as-keyed | |
# http://vaidehijoshi.github.io/blog/2015/10/13/stop-worrying-and-start-being-concerned-activesupport-concerns/ | |
module KeyedModel | |
extend ActiveSupport::Concern | |
KEY_CREATION_RETRIES = 100 | |
KEY_LENGTH = 8 | |
included do | |
if ActiveRecord::Base.connection.table_exists?(self.table_name) && columns_hash["key"].nil? | |
raise "Missing `key` column. Please ensure it was added in a migration via generator (easiest for UNIQUE index)" | |
end | |
before_validation(:create_key, :on => :create) | |
end | |
class_methods do | |
# DEV: We don't extend `find` so we don't back ourselves into a corner with type inference | |
# An example failure would be moving to UUIDs which are also string based | |
# it would make a lot of replacements for `find` or add computation complexity | |
def key_exists?(key_val) | |
return exists?(:key => key_val) | |
end | |
def generate_key() | |
# http://api.rubyonrails.org/classes/SecureRandom.html | |
# A-Z, a-z, 0-9 except for visually similar characters (i.e. 0 vs O, I vs l) | |
return SecureRandom.base58(KEY_LENGTH) | |
end | |
def from_param(param) | |
return find_by_key!(param) | |
end | |
end | |
def to_param | |
return self.key | |
end | |
protected | |
def create_key | |
key_val = nil | |
KEY_CREATION_RETRIES.times do | |
key_val = self.class.generate_key() | |
break if not self.class.key_exists? key_val | |
key_val = nil | |
end | |
if key_val.nil? | |
raise "Could not find unique key in #{KEY_CREATION_RETRIES} tries. Please expand `key` size for #{self.class.name}" | |
end | |
self.key = key_val | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment