Created
December 14, 2020 22:57
-
-
Save inopinatus/1b4f55cf06a53aba66f7fd0b2bbb0f0b to your computer and use it in GitHub Desktop.
Value object that replaced an enum
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
# app/models/organisation.rb | |
# schema like: | |
# | |
# create_table "organisations", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| | |
# t.string "transponder", default: "my_laps", null: false | |
# | |
class Organisation < ApplicationRecord | |
attribute :transponder, TransponderType.new |
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
# app/lib/transponder.rb | |
module Transponder | |
class << self | |
def find(transponder_name) | |
transponders[transponder_name.to_sym] || Transponder::None | |
end | |
def register_transponder(transponder_name, klass) | |
transponders[transponder_name.to_sym] = klass | |
end | |
def known | |
transponders.keys | |
end | |
private | |
def transponders | |
@_transponders ||= {} | |
end | |
end | |
class Base | |
include Comparable | |
def self.identifier | |
name.demodulize.underscore.to_sym | |
end | |
def inspect | |
"#<Transponder:#{self.class.identifier}>" | |
end | |
def description | |
raise NotImplementedError | |
end | |
def format_description | |
raise NotImplementedError | |
end | |
def input_pattern | |
raise NotImplementedError | |
end | |
def regex | |
raise NotImplementedError | |
end | |
def normalize(value) | |
return nil if value.blank? | |
value.strip.upcase | |
end | |
def valid?(value) | |
regex.match?(value) | |
end | |
def <=>(other) | |
self.class <=> other.class | |
end | |
def to_s | |
self.class.identifier.to_s | |
end | |
def to_partial_path | |
"transponders/#{self}" | |
end | |
def blank? | |
false | |
end | |
private | |
def self.inherited(subclass) | |
Transponder.register_transponder(subclass.identifier, subclass) | |
end | |
end | |
class None < Base | |
def description | |
"None" | |
end | |
def regex | |
// | |
end | |
def format_description | |
"(blank)" | |
end | |
def blank? | |
true | |
end | |
def to_s | |
"" | |
end | |
def input_pattern | |
"" | |
end | |
def to_partial_path | |
"transponders/none" | |
end | |
end | |
class MyLaps < Base | |
def description | |
"MyLaps" | |
end | |
def format_description | |
"AA-12345" | |
end | |
def input_pattern | |
'^[a-zA-Z]{2}-\d{5}$' | |
end | |
def regex | |
/\A[a-zA-Z]{2}-[0-9]{3,8}\z/ | |
end | |
end | |
class HexQuad < Base | |
def description | |
"Hex Quad" | |
end | |
def format_description | |
"four hex digits" | |
end | |
def input_pattern | |
'^[0-9A-Fa-f]{4}$' | |
end | |
def regex | |
/\A[0-9A-F]{4}\z/ | |
end | |
end | |
end |
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
# app/types/transponder_type.rb | |
class TransponderType < ActiveModel::Type::Value | |
def cast(value) | |
case value | |
when String, Symbol then Transponder.find(value).new | |
when Transponder::Base then value | |
when nil then Transponder::None | |
else fail TypeError, "can't make Transponder from #{value.inspect}" | |
end | |
end | |
def serialize(value) | |
value.to_s | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment