class Card::Codename
{Card}‘s names can be changed, and therefore names should not be directly mentioned in code, lest a name change break the application.
Instead, a {Card} that needs specific code manipulations should be given a {Codename}, which will not change even if the card’s name does.
An administrator might add to the Company card via the RESTful web API with a url like
/update/CARDNAME?card[codename]=CODENAME
…or via the api like
Card[CARDNAME].update! codename: CODENAME
Generally speaking, codenames are represented by Symbols.
The {Codename} class provides a fast cache for this slow-changing data. Every process maintains a complete cache that is not frequently reset
Public Class Methods
returns codename for id and id for codename @param codename [Integer, Symbol, String, Card::Name
] @return [Symbol]
# File lib/card/codename.rb, line 27 def [] codename case codename when Integer codehash[codename] when Symbol, String codehash.key?(codename.to_sym) ? codename.to_sym : nil end end
# File lib/card/codename.rb, line 49 def card codename if (card_id = id(codename)) Card[card_id] elsif block_given? yield end end
a Hash in which Symbol keys have Integer values and vice versa @return [Hash]
# File lib/card/codename.rb, line 65 def codehash @codehash ||= load_codehash end
# File lib/card/codename.rb, line 57 def exist? codename id(codename).present? end
# File lib/card/codename.rb, line 87 def generate_id_constants # If a card has the codename _example_, then Card::ExampleID will # return the id for that card. codehash.each do |codename, id| next unless codename.is_a?(Symbol) && !codename.to_s.match?(/\W/) id_constant codename, id end end
# File lib/card/codename.rb, line 36 def id codename case codename when Symbol, String codehash[codename.to_sym] when Integer codehash.key?(codename) ? codename : nil end end
@param codename [Symbol, String] @return [Integer]
# File lib/card/codename.rb, line 77 def id! codename id(codename) || unknown_codename!(codename) end
# File lib/card/codename.rb, line 45 def name codename=nil id(codename)&.cardname end
@param codename [Symbol, String] @return [Card::Name]
# File lib/card/codename.rb, line 83 def name! codename id!(codename)&.cardname end
# File lib/card/codename.rb, line 97 def recode oldcode, newcode return unless id(oldcode) && !id(newcode) puts "recode #{oldcode}, #{newcode}" Card.where(codename: oldcode).take.update_column :codename, newcode reset_cache end
clear cache both locally and in cache
# File lib/card/codename.rb, line 70 def reset_cache @codehash = nil ::Card.cache.delete "CODEHASH" end
Private Class Methods
@todo remove duplicate checks here; should be caught upon creation
# File lib/card/codename.rb, line 118 def check_duplicates codehash, codename, card_id return unless codehash.key?(codename) || codehash.key?(card_id) Rails.logger.debug "dup codename: #{codename}, "\ "ID:#{card_id} (#{codehash[codename]})" end
iterate through every card with a codename @yieldparam codename [Symbol] @yieldparam id [Integer]
# File lib/card/codename.rb, line 110 def each_codenamed_card sql = "select id, codename from cards where codename is not NULL" ActiveRecord::Base.connection.select_all(sql).each do |row| yield row["codename"].to_sym, row["id"].to_i end end
# File lib/card/codename.rb, line 132 def generate_codehash hash = {} each_codenamed_card do |codename, card_id| check_duplicates hash, codename, card_id hash[codename] = card_id hash[card_id] = codename end hash end
# File lib/card/codename.rb, line 147 def id_constant codename, id=nil id ||= id! codename Card.const_get_or_set("#{codename.to_s.camelize}ID") { id } end
generate Hash for @codehash and put it in the cache
# File lib/card/codename.rb, line 126 def load_codehash ::Card.cache.fetch("CODEHASH") do generate_codehash end end
# File lib/card/codename.rb, line 142 def unknown_codename! mark raise Card::Error::CodenameNotFound, ::I18n.t(:lib_exception_unknown_codename, codename: mark) end