Module: Fixtury::SchemaNode
- Extended by:
- ActiveSupport::Concern
- Included in:
- Definition, Schema
- Defined in:
- lib/fixtury/schema_node.rb
Overview
This module is used to provide a common interface for all nodes in the schema tree. Namespaces and fixture definitions adhere to this interface and are provided with common behaviors for registration, traversal, inspection, etc
Constant Summary collapse
- VALID_NODE_NAME =
/^[a-zA-Z0-9_]*$/
Instance Method Summary collapse
-
#acts_like_fixtury_schema_node? ⇒ Boolean
Adherance to the acts_like? interface.
-
#add_child(child) ⇒ Fixtury::Errors::AlreadyDefinedError
Adds child to the node’s children hash as long as another is not already defined.
-
#apply_options!(opts = {}) ⇒ void
Applies options to the node and raises if a collision occurs.
-
#first_ancestor? ⇒ TrueClass, FalseClass
Is the current node the first ancestor?.
-
#get(search) ⇒ Fixtury::SchemaNode, NilClass
(also: #[])
Retrieves a node in the tree relative to self.
-
#get!(search) ⇒ Object
Performs get() but raises if the result is nil.
-
#initialize(name:, parent: nil, **options) ⇒ Fixtury::SchemaNode
Constructs a new SchemaNode object.
-
#inspect ⇒ String
Inspect the SchemaNode object without representing the parent or children to avoid large prints.
-
#isolation_key(default: true) ⇒ String, NilClass
Determines the isolation key in a top-down manner.
-
#schema_node_type ⇒ String
An identifier used during the printing of the tree structure.
-
#structure(prefix = "") ⇒ String
Generates a string representing the structure of the schema tree.
Instance Method Details
#acts_like_fixtury_schema_node? ⇒ Boolean
Adherance to the acts_like? interface
52 53 54 |
# File 'lib/fixtury/schema_node.rb', line 52 def acts_like_fixtury_schema_node? true end |
#add_child(child) ⇒ Fixtury::Errors::AlreadyDefinedError
Adds child to the node’s children hash as long as another is not already defined.
61 62 63 64 65 66 67 |
# File 'lib/fixtury/schema_node.rb', line 61 def add_child(child) if children.key?(child.name) && children[child.name] != child raise Errors::AlreadyDefinedError, child.pathname end children[child.name] = child end |
#apply_options!(opts = {}) ⇒ void
This method returns an undefined value.
Applies options to the node and raises if a collision occurs. This is useful for reopening a node and ensuring options are not altered.
164 165 166 167 168 169 170 171 172 |
# File 'lib/fixtury/schema_node.rb', line 164 def (opts = {}) opts.each do |key, value| if .key?(key) && [key] != value raise Errors::OptionCollisionError.new(name, key, [key], value) end [key] = value end end |
#first_ancestor? ⇒ TrueClass, FalseClass
Is the current node the first ancestor?
72 73 74 |
# File 'lib/fixtury/schema_node.rb', line 72 def first_ancestor? parent.nil? end |
#get(search) ⇒ Fixtury::SchemaNode, NilClass Also known as: []
Retrieves a node in the tree relative to self. Absolute and relative searches are accepted. The potential absolute paths are determined by a Fixtury::PathResolver instance relative to this node’s pathname.
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/fixtury/schema_node.rb', line 113 def get(search) raise ArgumentError, "`search` must be provided" if search.blank? resolver = Fixtury::PathResolver.new(namespace: self.pathname, search: search) resolver.possible_absolute_paths.each do |path| target = first_ancestor segments = path.split("/") segments.reject!(&:blank?) segments.shift if segments.first == target.name segments.each do |segment| target = target.children[segment] break unless target end return target if target end nil end |
#get!(search) ⇒ Object
Performs get() but raises if the result is nil. (see #get)
98 99 100 101 102 103 |
# File 'lib/fixtury/schema_node.rb', line 98 def get!(search) thing = get(search) raise Errors::SchemaNodeNotDefinedError.new(pathname, search) unless thing thing end |
#initialize(name:, parent: nil, **options) ⇒ Fixtury::SchemaNode
Constructs a new SchemaNode object.
22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/fixtury/schema_node.rb', line 22 def initialize(name:, parent: nil, **) name = name.to_s raise ArgumentError, "#{name.inspect} is an invalid node name" unless name.match?(VALID_NODE_NAME) @name = name @parent = parent @pathname = File.join(*[parent&.pathname, "/", @name].compact).to_s @children = {} @options = {} () @first_ancestor = @parent&.first_ancestor || self @parent&.add_child(self) end |
#inspect ⇒ String
Inspect the SchemaNode object without representing the parent or children to avoid large prints.
40 41 42 |
# File 'lib/fixtury/schema_node.rb', line 40 def inspect "#{self.class}(pathname: #{pathname.inspect}, children: #{children.size})" end |
#isolation_key(default: true) ⇒ String, NilClass
Determines the isolation key in a top-down manner. It first accepts an isolation key set by the parent, then it checks for an isolation key set by the node itself. If no isolation key is found, it defaults to the node’s name unless default is set to falsy.
85 86 87 88 89 90 91 92 93 |
# File 'lib/fixtury/schema_node.rb', line 85 def isolation_key(default: true) from_parent = parent&.isolation_key(default: nil) return from_parent if from_parent value = [:isolate] || default value = (value == true ? pathname : value&.to_s).presence value = (value == "/" ? nil : value) # special case to accommodate root nodes value.presence end |
#schema_node_type ⇒ String
An identifier used during the printing of the tree structure.
47 48 49 |
# File 'lib/fixtury/schema_node.rb', line 47 def schema_node_type self.class.name.demodulize.underscore end |
#structure(prefix = "") ⇒ String
Generates a string representing the structure of the schema tree. The string will be in the form of “type:name(options)”. The children will be on the next line and indented by two spaces.
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/fixtury/schema_node.rb', line 140 def structure(prefix = "") out = [] opts = .except(:isolate) opts.compact! my_structure = +"#{prefix}#{schema_node_type}:#{name}" iso = isolation_key(default: nil) my_structure << "[#{iso}]" if iso my_structure << "(#{opts.to_a.map { |k, v| "#{k}: #{v.inspect}" }.join(", ")})" if opts.present? out << my_structure children.each_value do |child| out << child.structure("#{prefix} ") end out.join("\n") end |