Class: Anchormodel
- Inherits:
-
Object
- Object
- Anchormodel
- Defined in:
- lib/anchormodel.rb,
lib/anchormodel/version.rb,
lib/anchormodel/simple_form_inputs/helpers/anchormodel_inputs_common.rb
Overview
An Anchormodel is a registry of named constants that behave like first-class objects. It is a richer alternative to Rails Enums: each entry is a real Ruby instance that can carry behavior and per-key attributes while still being persistable to a String column in the database.
Place anchormodel subclasses under app/anchormodels/your_anchor_model.rb so Rails
autoloading picks them up. Refer to the README for usage.
Defined Under Namespace
Modules: ModelMixin, SimpleFormInputs, Util, Version Classes: ActiveModelTypeValueMulti, ActiveModelTypeValueSingle, Attribute, InvalidKey
Instance Attribute Summary collapse
-
#index ⇒ Object
readonly
Returns the value of attribute index.
-
#key ⇒ Object
readonly
Returns the value of attribute key.
Class Method Summary collapse
-
.all ⇒ Array<Anchormodel>
All registered entries of this subclass, in declaration order.
-
.find(key) ⇒ Anchormodel?
Retrieves the entry registered under
key. -
.first ⇒ Anchormodel?
Shorthand for
all.first. -
.form_collection ⇒ Array<Array(String,String)>
Builds a
[label, key_string]tuple list suitable for Rails form select helpers. -
.setup! ⇒ void
Initializes the per-subclass registry on first use.
Instance Method Summary collapse
-
#==(other) ⇒ Boolean
(also: #eql?)
Two anchormodels are equal iff they have the same concrete class and key.
-
#as_json ⇒ String
JSON serialization returns the key as a String so anchormodels round-trip cleanly through JSON (e.g. for API payloads).
-
#hash ⇒ Integer
Hash matches
==(class + key) soSetandHashmembership work correctly even for copies (dup, Marshal round-trip) of the singleton entries. -
#initialize(key, **attributes) ⇒ Anchormodel
constructor
Registers a new entry.
-
#inspect ⇒ String
Debug representation like
"#<Role<admin>:HASH>". -
#label ⇒ String
Returns a translatable label for this entry, compatible with the Rails FastGettext gem.
-
#to_s ⇒ String
Same as #inspect.
Constructor Details
#initialize(key, **attributes) ⇒ Anchormodel
Registers a new entry. Called in the body of an Anchormodel subclass.
All keyword arguments become instance attributes accessible via attr_reader.
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/anchormodel.rb', line 115 def initialize(key, **attributes) self.class.setup! unless self.class.setup_completed @key = key.to_sym @index = entries_list.count # Save attributes as instance variables attributes.each do |k, v| instance_variable_set(:"@#{k}", v) end # Register self fail("Duplicate anchor model key #{key.inspect} for #{self.class}.") if entries_hash.key?(key) entries_list << self entries_hash[key] = self # Register valid keys valid_keys << key # Define boolean reader self.class.define_method(:"#{key}?") do @key == key end end |
Instance Attribute Details
#index ⇒ Object (readonly)
Returns the value of attribute index.
37 38 39 |
# File 'lib/anchormodel.rb', line 37 def index @index end |
#key ⇒ Object (readonly)
Returns the value of attribute key.
33 34 35 |
# File 'lib/anchormodel.rb', line 33 def key @key end |
Class Method Details
.all ⇒ Array<Anchormodel>
Returns All registered entries of this subclass, in declaration order.
63 64 65 |
# File 'lib/anchormodel.rb', line 63 def self.all entries_list end |
.find(key) ⇒ Anchormodel?
Retrieves the entry registered under key.
99 100 101 102 |
# File 'lib/anchormodel.rb', line 99 def self.find(key) return nil if key.nil? return entries_hash[key.to_sym] || raise(InvalidKey, "Retrieved undefined anchor model key #{key.inspect} for #{inspect}.") end |
.first ⇒ Anchormodel?
Shorthand for all.first. Provided so callers can avoid Rubocop's
Style/FirstElementInCollection-style warnings on Foo.all.first.
70 71 72 |
# File 'lib/anchormodel.rb', line 70 def self.first all.first end |
.form_collection ⇒ Array<Array(String,String)>
Builds a [label, key_string] tuple list suitable for Rails form select helpers.
78 79 80 |
# File 'lib/anchormodel.rb', line 78 def self.form_collection entries_list.map { |el| [el.label, el.key.to_s] } end |
.setup! ⇒ void
This method returns an undefined value.
Initializes the per-subclass registry on first use. Called automatically from
the first new invocation. Each subclass gets its own duped copies of the
registry class attributes to prevent cross-class pollution.
You normally do not need to call this directly.
52 53 54 55 56 57 58 |
# File 'lib/anchormodel.rb', line 52 def self.setup! fail("`setup!` was called twice for Anchormodel subclass #{self}.") if setup_completed self.entries_list = entries_list.dup self.entries_hash = entries_hash.dup self.valid_keys = valid_keys.dup self.setup_completed = true end |
Instance Method Details
#==(other) ⇒ Boolean Also known as: eql?
Two anchormodels are equal iff they have the same concrete class and key. Different subclasses sharing a key are not equal.
144 145 146 |
# File 'lib/anchormodel.rb', line 144 def ==(other) self.class == other.class && key == other.key end |
#as_json ⇒ String
JSON serialization returns the key as a String so anchormodels round-trip cleanly through JSON (e.g. for API payloads).
184 185 186 |
# File 'lib/anchormodel.rb', line 184 def as_json key.to_s end |
#hash ⇒ Integer
Hash matches == (class + key) so Set and Hash membership work correctly
even for copies (dup, Marshal round-trip) of the singleton entries.
152 153 154 |
# File 'lib/anchormodel.rb', line 152 def hash [self.class, key].hash end |
#inspect ⇒ String
Returns Debug representation like "#<Role<admin>:HASH>".
167 168 169 |
# File 'lib/anchormodel.rb', line 167 def inspect "#<#{self.class.name}<#{key}>:#{hash}>" end |
#label ⇒ String
Returns a translatable label for this entry, compatible with the
Rails FastGettext gem.
The translation key is "<SubclassName>|<Humanized key>".
162 163 164 |
# File 'lib/anchormodel.rb', line 162 def label I18n.t("#{self.class.name.demodulize}|#{key.to_s.humanize}") end |
#to_s ⇒ String
Same as #inspect. Anchormodel intentionally overrides to_s so string
interpolation in templates is unambiguous; render #label or #key directly
if you want a user-facing form.
175 176 177 |
# File 'lib/anchormodel.rb', line 175 def to_s inspect end |