Class: Hecks::Fqn

Inherits:
Object
  • Object
show all
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

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(realm:, domain:, version: nil, aggregate:, verb:, kind:) ⇒ Fqn

Returns a new instance of Fqn.

Raises:



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

#aggregateObject (readonly)

Returns the value of attribute aggregate.



9
10
11
# File 'lib/hecks/fqn.rb', line 9

def aggregate
  @aggregate
end

#domainObject (readonly)

Returns the value of attribute domain.



9
10
11
# File 'lib/hecks/fqn.rb', line 9

def domain
  @domain
end

#realmObject (readonly)

Returns the value of attribute realm.



9
10
11
# File 'lib/hecks/fqn.rb', line 9

def realm
  @realm
end

#verbObject (readonly)

Returns the value of attribute verb.



9
10
11
# File 'lib/hecks/fqn.rb', line 9

def verb
  @verb
end

#versionObject (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

Returns:

  • (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

Raises:



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

Returns:

  • (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

Raises:



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

Returns:

  • (Boolean)


63
# File 'lib/hecks/fqn.rb', line 63

def command? = @kind == :command

#hashObject



74
# File 'lib/hecks/fqn.rb', line 74

def hash = to_s.hash

#kindObject



65
# File 'lib/hecks/fqn.rb', line 65

def kind     = @kind

#query?Boolean

Returns:

  • (Boolean)


64
# File 'lib/hecks/fqn.rb', line 64

def query?   = @kind == :query

#to_sObject



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