Class: Fixtury::Store
- Inherits:
-
Object
- Object
- Fixtury::Store
- Defined in:
- lib/fixtury/store.rb
Overview
A store is a container for built fixture references. It is responsible for loading and caching fixtures based on a schema and a locator.
Instance Attribute Summary collapse
-
#locator ⇒ Object
readonly
Returns the value of attribute locator.
-
#schema ⇒ Object
readonly
Returns the value of attribute schema.
Instance Method Summary collapse
-
#clear_stale_references! ⇒ void
Clear any references that are beyond their ttl or are no longer recognizable by the locator.
-
#get(search) ⇒ Object
(also: #[])
Fetch a fixture by name.
-
#initialize(schema: nil) ⇒ Store
constructor
A new instance of Store.
-
#inspect ⇒ String
Summarize the current state of the store.
-
#load_all(schema = self.schema) ⇒ void
Load all fixtures in the target schema, defaulting to the store’s schema.
-
#loaded?(search) ⇒ TrueClass, FalseClass
Is a fixture for the given search already loaded?.
- #loaded_isolation_keys ⇒ Object
- #references ⇒ Object
- #references=(value) ⇒ Object
-
#reset ⇒ Object
Empty the store of any references and loaded isolation keys.
-
#with_relative_schema(schema) {|void| ... } ⇒ Object
Temporarily set a contextual schema to use for loading fixtures.
Constructor Details
#initialize(schema: nil) ⇒ Store
Returns a new instance of Store.
17 18 19 20 21 |
# File 'lib/fixtury/store.rb', line 17 def initialize(schema: nil) @schema = schema || ::Fixtury.schema @locator = ::Fixtury::Locator.from(::Fixtury.configuration.locator_backend) self.references = ::Fixtury.configuration.stored_references end |
Instance Attribute Details
#locator ⇒ Object (readonly)
Returns the value of attribute locator.
13 14 15 |
# File 'lib/fixtury/store.rb', line 13 def locator @locator end |
#schema ⇒ Object (readonly)
Returns the value of attribute schema.
14 15 16 |
# File 'lib/fixtury/store.rb', line 14 def schema @schema end |
Instance Method Details
#clear_stale_references! ⇒ void
This method returns an undefined value.
Clear any references that are beyond their ttl or are no longer recognizable by the locator.
60 61 62 63 64 65 66 |
# File 'lib/fixtury/store.rb', line 60 def clear_stale_references! references.delete_if do |name, ref| stale = reference_stale?(ref) log("expiring #{name}", level: LOG_LEVEL_DEBUG) if stale stale end end |
#get(search) ⇒ Object Also known as: []
Fetch a fixture by name. This will load the fixture if it has not been loaded yet. If a definition contains an isolation key, all fixtures with the same isolation key will be loaded.
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/fixtury/store.rb', line 115 def get(search) log("getting #{search} relative to #{schema.pathname}", level: LOG_LEVEL_DEBUG) # Find the definition. dfn = schema.get!(search) raise ArgumentError, "#{search.inspect} must refer to a definition" unless dfn.acts_like?(:fixtury_definition) pathname = dfn.pathname isokey = dfn.isolation_key # Ensure that if we're part of an isolation group, we load all the fixtures in that group. maybe_load_isolation_dependencies(isokey) # See if we already hold a reference to the fixture. ref = references[pathname] # If the reference is a placeholder, we have a circular dependency. if ref&.holder? raise Errors::CircularDependencyError, pathname end # If the reference is stale, we should refresh it. # We do so by clearing it from the store and setting the reference to nil. if ref && reference_stale?(ref) log("refreshing #{pathname}", level: LOG_LEVEL_DEBUG) clear_reference(pathname) ref = nil end value = nil if ref log("hit #{pathname}", level: LOG_LEVEL_ALL) value = locator.load(ref.locator_key) if value.nil? clear_reference(pathname) ref = nil log("missing #{pathname}", level: LOG_LEVEL_ALL) end end if value.nil? # set the references to a holder value so any recursive behavior ends up hitting a circular dependency error if the same fixture load is attempted references[pathname] = ::Fixtury::Reference.holder(pathname) begin executor = ::Fixtury::DefinitionExecutor.new(store: self, definition: dfn) output = executor.call value = output.value rescue StandardError clear_reference(pathname) raise end log("store #{pathname}", level: LOG_LEVEL_DEBUG) locator_key = locator.dump(output.value, context: pathname) reference_opts = {} reference_opts.merge!(output.) reference_opts[:isolation_key] = isokey unless isokey == pathname references[pathname] = ::Fixtury::Reference.new( pathname, locator_key, **reference_opts ) end value end |
#inspect ⇒ String
Summarize the current state of the store.
47 48 49 50 51 52 53 54 55 |
# File 'lib/fixtury/store.rb', line 47 def inspect parts = [] parts << "schema: #{schema.inspect}" parts << "locator: #{locator.inspect}" parts << "ttl: #{ttl.inspect}" if ttl parts << "references: #{references.size}" "#{self.class}(#{parts.join(", ")})" end |
#load_all(schema = self.schema) ⇒ void
This method returns an undefined value.
Load all fixtures in the target schema, defaulting to the store’s schema. This will load all fixtures in the schema and any child schemas.
73 74 75 76 77 78 |
# File 'lib/fixtury/store.rb', line 73 def load_all(schema = self.schema) schema.children.each_value do |item| get(item.pathname) if item.acts_like?(:fixtury_definition) load_all(item) if item.acts_like?(:fixtury_schema) end end |
#loaded?(search) ⇒ TrueClass, FalseClass
Is a fixture for the given search already loaded?
98 99 100 101 102 103 104 |
# File 'lib/fixtury/store.rb', line 98 def loaded?(search) dfn = schema.get!(search) ref = references[dfn.pathname] result = ref&.real? log(result ? "hit #{dfn.pathname}" : "miss #{dfn.pathname}", level: LOG_LEVEL_ALL) result end |
#loaded_isolation_keys ⇒ Object
33 34 35 36 |
# File 'lib/fixtury/store.rb', line 33 def loaded_isolation_keys @loaded_isolation_keys ||= ::Concurrent::ThreadLocalVar.new({}) @loaded_isolation_keys.value end |
#references ⇒ Object
23 24 25 26 |
# File 'lib/fixtury/store.rb', line 23 def references @references ||= ::Concurrent::ThreadLocalVar.new({}) @references.value end |
#references=(value) ⇒ Object
28 29 30 31 |
# File 'lib/fixtury/store.rb', line 28 def references=(value) references.clear @references.value = value end |
#reset ⇒ Object
Empty the store of any references and loaded isolation keys.
39 40 41 42 |
# File 'lib/fixtury/store.rb', line 39 def reset references.clear loaded_isolation_keys.clear end |
#with_relative_schema(schema) {|void| ... } ⇒ Object
Temporarily set a contextual schema to use for loading fixtures. This is useful when evaluating dependencies of a definition while still storing the results.
86 87 88 89 90 91 92 |
# File 'lib/fixtury/store.rb', line 86 def with_relative_schema(schema) prior = @schema @schema = schema yield ensure @schema = prior end |