Class: Hecks::Fqn
- Inherits:
-
Object
- Object
- Hecks::Fqn
- Defined in:
- lib/hecks/fqn.rb
Overview
A public Bluebook command/query address.
Realm is deployment identity from a world. Domain@version pins a domain contract; an unpinned domain is the world's configured latest alias.
Defined Under Namespace
Classes: Invalid
Instance Attribute Summary collapse
-
#aggregate ⇒ Object
readonly
Returns the value of attribute aggregate.
-
#domain ⇒ Object
readonly
Returns the value of attribute domain.
-
#realm ⇒ Object
readonly
Returns the value of attribute realm.
-
#verb ⇒ Object
readonly
Returns the value of attribute verb.
-
#version ⇒ Object
readonly
Returns the value of attribute version.
Class Method Summary collapse
- .command(realm:, domain:, aggregate:, command:, version: nil) ⇒ Object
- .command_name?(name) ⇒ Boolean
- .parse(text) ⇒ Object
- .query(realm:, domain:, aggregate: nil, query:, version: nil) ⇒ Object
- .query_name?(name) ⇒ Boolean
- .split_domain(value) ⇒ Object
Instance Method Summary collapse
- #==(other) ⇒ Object (also: #eql?)
- #command? ⇒ Boolean
- #hash ⇒ Object
-
#initialize(realm:, domain:, version: nil, aggregate:, verb:, kind:) ⇒ Fqn
constructor
A new instance of Fqn.
- #kind ⇒ Object
- #query? ⇒ Boolean
- #to_s ⇒ Object
Constructor Details
#initialize(realm:, domain:, version: nil, aggregate:, verb:, kind:) ⇒ Fqn
Returns a new instance of Fqn.
51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/hecks/fqn.rb', line 51 def initialize(realm:, domain:, version: nil, aggregate:, verb:, kind:) @realm = realm && segment(realm, "realm") @domain = segment(domain, "domain") @version = version && segment(version, "version") @aggregate = aggregate && segment(aggregate, "aggregate") @verb = segment(verb, "verb") @kind = kind.to_sym valid = command? ? self.class.command_name?(@verb) : self.class.query_name?(@verb) raise Invalid, "#{@kind} FQN has an invalid verb #{@verb.inspect}" unless valid end |
Instance Attribute Details
#aggregate ⇒ Object (readonly)
Returns the value of attribute aggregate.
9 10 11 |
# File 'lib/hecks/fqn.rb', line 9 def aggregate @aggregate end |
#domain ⇒ Object (readonly)
Returns the value of attribute domain.
9 10 11 |
# File 'lib/hecks/fqn.rb', line 9 def domain @domain end |
#realm ⇒ Object (readonly)
Returns the value of attribute realm.
9 10 11 |
# File 'lib/hecks/fqn.rb', line 9 def realm @realm end |
#verb ⇒ Object (readonly)
Returns the value of attribute verb.
9 10 11 |
# File 'lib/hecks/fqn.rb', line 9 def verb @verb end |
#version ⇒ Object (readonly)
Returns the value of attribute version.
9 10 11 |
# File 'lib/hecks/fqn.rb', line 9 def version @version end |
Class Method Details
.command(realm:, domain:, aggregate:, command:, version: nil) ⇒ Object
11 12 13 |
# File 'lib/hecks/fqn.rb', line 11 def self.command(realm:, domain:, aggregate:, command:, version: nil) new(realm: realm, domain: domain, version: version, aggregate: aggregate, verb: command, kind: :command) end |
.command_name?(name) ⇒ Boolean
48 |
# File 'lib/hecks/fqn.rb', line 48 def self.command_name?(name) = /\A[A-Z][A-Za-z0-9]*\z/.match?(name.to_s) |
.parse(text) ⇒ Object
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/hecks/fqn.rb', line 19 def self.parse(text) head, separator, verb = text.to_s.rpartition(".") raise Invalid, "FQN must be Realm::Domain::Aggregate.verb — got #{text.inspect}" if separator.empty? segments = head.split("::", -1) raise Invalid, "FQN must be Realm::Domain::Aggregate.verb — got #{text.inspect}" unless [1, 2, 3].include?(segments.length) && segments.none?(&:empty?) && !verb.empty? realm, domain_spec, aggregate = case segments.length when 3 then segments # A two-segment lowercase address is the # public realm/domain form for a # domain-level read model. when 2 then query_name?(verb) ? [segments[0], segments[1], nil] : [nil, *segments] else [nil, segments.first, nil] end domain, version = split_domain(domain_spec) kind = if command_name?(verb) :command elsif query_name?(verb) :query else raise Invalid, "FQN verb must be PascalCase command or snake_case query — got #{text.inspect}" end raise Invalid, "domain-level FQNs are query-only — got #{text.inspect}" if aggregate.nil? && kind == :command new(realm: realm, domain: domain, version: version, aggregate: aggregate, verb: verb, kind: kind) end |
.query(realm:, domain:, aggregate: nil, query:, version: nil) ⇒ Object
15 16 17 |
# File 'lib/hecks/fqn.rb', line 15 def self.query(realm:, domain:, aggregate: nil, query:, version: nil) new(realm: realm, domain: domain, version: version, aggregate: aggregate, verb: query, kind: :query) end |
.query_name?(name) ⇒ Boolean
49 |
# File 'lib/hecks/fqn.rb', line 49 def self.query_name?(name) = /\A[a-z][a-z0-9_]*\z/.match?(name.to_s) |
.split_domain(value) ⇒ Object
78 79 80 81 82 83 84 |
# File 'lib/hecks/fqn.rb', line 78 def self.split_domain(value) domain, version, extra = value.to_s.split("@", 3) raise Invalid, "FQN domain version is malformed: #{value.inspect}" if domain.empty? || extra || (value.include?("@") && version.to_s.empty?) [domain, version] end |
Instance Method Details
#==(other) ⇒ Object Also known as: eql?
72 |
# File 'lib/hecks/fqn.rb', line 72 def ==(other) = other.is_a?(Fqn) && to_s == other.to_s |
#command? ⇒ Boolean
63 |
# File 'lib/hecks/fqn.rb', line 63 def command? = @kind == :command |
#hash ⇒ Object
74 |
# File 'lib/hecks/fqn.rb', line 74 def hash = to_s.hash |
#kind ⇒ Object
65 |
# File 'lib/hecks/fqn.rb', line 65 def kind = @kind |
#query? ⇒ Boolean
64 |
# File 'lib/hecks/fqn.rb', line 64 def query? = @kind == :query |
#to_s ⇒ Object
67 68 69 70 |
# File 'lib/hecks/fqn.rb', line 67 def to_s domain = @version ? "#{@domain}@#{@version}" : @domain [[@realm, domain, @aggregate].compact.join("::"), @verb].join(".") end |