Class: SpecForge::Attribute
- Inherits:
-
Object
- Object
- SpecForge::Attribute
- Extended by:
- Resolvable
- Includes:
- Resolvable
- Defined in:
- lib/spec_forge/attribute.rb,
lib/spec_forge/attribute/faker.rb,
lib/spec_forge/attribute/regex.rb,
lib/spec_forge/attribute/factory.rb,
lib/spec_forge/attribute/literal.rb,
lib/spec_forge/attribute/matcher.rb,
lib/spec_forge/attribute/generate.rb,
lib/spec_forge/attribute/template.rb,
lib/spec_forge/attribute/variable.rb,
lib/spec_forge/attribute/chainable.rb,
lib/spec_forge/attribute/transform.rb,
lib/spec_forge/attribute/resolvable.rb,
lib/spec_forge/attribute/environment.rb,
lib/spec_forge/attribute/parameterized.rb,
lib/spec_forge/attribute/resolvable_hash.rb,
lib/spec_forge/attribute/resolvable_array.rb,
lib/spec_forge/attribute/resolvable_struct.rb
Overview
Base class for all attribute types in SpecForge. Attributes represent values that can be transformed, resolved, or have special meaning in the context of specs and expectations.
The Attribute system handles dynamic data generation, variable references, matchers, transformations and other special values in YAML specs.
Defined Under Namespace
Modules: Chainable, Resolvable Classes: Environment, Factory, Faker, Generate, Literal, Matcher, Parameterized, Regex, ResolvableArray, ResolvableHash, ResolvableStruct, Template, Transform, Variable
Instance Attribute Summary collapse
-
#input ⇒ Object
readonly
The original input value.
Class Method Summary collapse
-
.from(value, **options) ⇒ Attribute
Creates an Attribute instance based on the input value's type and content.
-
.from_hash(hash, **options) ⇒ Attribute
Creates an Attribute instance from a hash.
-
.from_string(string, **options) ⇒ Attribute
Creates an Attribute instance from a string.
Instance Method Summary collapse
-
#==(other) ⇒ Boolean
Compares this attributes input to other.
-
#initialize(input, **options) ⇒ Attribute
constructor
Creates a new attribute.
-
#resolve ⇒ Object
Performs recursive resolution of the attribute's value.
-
#resolve_as_matcher ⇒ RSpec::Matchers::BuiltIn::BaseMatcher
Converts the resolved value into an RSpec matcher.
-
#resolved ⇒ Object
Returns the fully evaluated result with complete recursive resolution.
-
#value ⇒ Object
Returns the processed value of this attribute.
Methods included from Resolvable
resolve_as_matcher_proc, resolve_proc, resolved_proc
Constructor Details
#initialize(input, **options) ⇒ Attribute
Creates a new attribute
132 133 134 135 |
# File 'lib/spec_forge/attribute.rb', line 132 def initialize(input, **) @input = input @options = end |
Instance Attribute Details
#input ⇒ Object (readonly)
The original input value
122 123 124 |
# File 'lib/spec_forge/attribute.rb', line 122 def input @input end |
Class Method Details
.from(value, **options) ⇒ Attribute
Creates an Attribute instance based on the input value's type and content. Recursively converts Array and Hash
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/spec_forge/attribute.rb', line 35 def self.from(value, **) case value when String from_string(value, **) when Hash from_hash(value, **) when Attribute, ResolvableArray, ResolvableHash, ResolvableStruct value when Array array = value.map { |v| Attribute.from(v, **) } ResolvableArray.new(array) when Struct, Data, OpenStruct ResolvableStruct.new(value) else Literal.new(value, **) end end |
.from_hash(hash, **options) ⇒ Attribute
Creates an Attribute instance from a hash
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/spec_forge/attribute.rb', line 97 def self.from_hash(hash, **) # Determine if the hash is an expanded macro call has_macro = ->(h, regex) { h.any? { |k, _| k.match?(regex) } } if has_macro.call(hash, Transform::KEYWORD_REGEX) Transform.from_hash(hash, **) elsif has_macro.call(hash, Generate::KEYWORD_REGEX) Generate.from_hash(hash, **) elsif has_macro.call(hash, Faker::KEYWORD_REGEX) Faker.from_hash(hash, **) elsif has_macro.call(hash, Matcher::KEYWORD_REGEX) Matcher.from_hash(hash, **) elsif has_macro.call(hash, Factory::KEYWORD_REGEX) Factory.from_hash(hash, **) else hash = hash.transform_values { |v| Attribute.from(v, **) } ResolvableHash.new(hash) end end |
.from_string(string, **options) ⇒ Attribute
Creates an Attribute instance from a string
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/spec_forge/attribute.rb', line 64 def self.from_string(string, **) klass = case string when Template::REGEX Template when Environment::KEYWORD_REGEX Environment when Factory::KEYWORD_REGEX Factory when Faker::KEYWORD_REGEX Faker when Matcher::KEYWORD_REGEX Matcher when Regex::KEYWORD_REGEX Regex else Literal end klass.new(string, **) end |
Instance Method Details
#==(other) ⇒ Boolean
Compares this attributes input to other
144 145 146 147 148 149 150 151 152 153 |
# File 'lib/spec_forge/attribute.rb', line 144 def ==(other) other = if other.is_a?(Attribute) other.input else other end input == other end |
#resolve ⇒ Object
Performs recursive resolution of the attribute's value. Handles nested arrays and hashes by recursively resolving their elements.
Unlike #resolved, this method doesn't cache results and can be used when fresh resolution is needed each time.
207 208 209 210 211 212 213 214 215 216 |
# File 'lib/spec_forge/attribute.rb', line 207 def resolve case value when Array value.map(&resolve_proc) when Hash value.transform_values(&resolve_proc) else value end end |
#resolve_as_matcher ⇒ RSpec::Matchers::BuiltIn::BaseMatcher
Converts the resolved value into an RSpec matcher
Transforms the attribute's resolved value into an appropriate RSpec matcher for use in expectations. Handles arrays, hashes, matchers, regexes, and literal values differently to produce the correct matcher type.
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 |
# File 'lib/spec_forge/attribute.rb', line 227 def resolve_as_matcher methods = Attribute::Matcher::MATCHER_METHODS case resolved when Array resolved_array = resolved.map(&resolve_as_matcher_proc) if resolved_array.size > 0 resolved_array else methods.eq([]) end when Hash resolved_hash = resolved.transform_values(&resolve_as_matcher_proc).stringify_keys if resolved_hash.size > 0 resolved_hash else methods.eq({}) end when Attribute::Matcher, Regexp methods.match(resolved) when RSpec::Matchers::BuiltIn::BaseMatcher, RSpec::Matchers::DSL::Matcher, Class resolved # Pass through else methods.eq(resolved) end end |
#resolved ⇒ Object
Returns the fully evaluated result with complete recursive resolution. Calls #value internally and then resolves all nested attributes, caching the result.
Use this when you need the final, fully-resolved value with all nested attributes fully evaluated to their primitive values.
189 190 191 |
# File 'lib/spec_forge/attribute.rb', line 189 def resolved @resolved ||= resolve end |
#value ⇒ Object
Returns the processed value of this attribute. Recursively calls #value on underlying attributes, but does NOT resolve all nested structures completely.
This returns an intermediate representation - for fully resolved values, use #resolve instead.
171 172 173 |
# File 'lib/spec_forge/attribute.rb', line 171 def value raise "not implemented" end |