Class: Gemstash::Resource
- Inherits:
-
Object
- Object
- Gemstash::Resource
- Includes:
- Env::Helper, Logging
- Defined in:
- lib/gemstash/storage.rb
Overview
A resource within the storage engine. The resource may have 1 or more files associated with it along with a metadata Hash that is stored in a YAML file.
Defined Under Namespace
Classes: VersionTooNew
Constant Summary collapse
- VERSION =
1
Constants included from Logging
Instance Attribute Summary collapse
-
#folder ⇒ Object
readonly
Returns the value of attribute folder.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
Instance Method Summary collapse
-
#content(key) ⇒ String
Fetch the content for the given
key
. -
#delete(key) ⇒ Gemstash::Resource
Delete the content for the given
key
. -
#exist?(key = nil) ⇒ Boolean
When
key
is nil, this will test if this resource exists with any content. -
#initialize(folder, name) ⇒ Resource
constructor
This object should not be constructed directly, but instead via Storage#resource.
-
#properties ⇒ Hash
Fetch the metadata properties for this resource.
-
#property?(*keys) ⇒ Boolean
Check if the metadata properties includes the
keys
. -
#save(content, properties = nil) ⇒ Gemstash::Resource
Save one or more files for this resource given by the
content
hash. -
#update_properties(props) ⇒ Gemstash::Resource
Update the metadata properties of this resource.
Methods included from Logging
#log, #log_error, logger, reset, setup_logger
Constructor Details
#initialize(folder, name) ⇒ Resource
This object should not be constructed directly, but instead via Storage#resource.
107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/gemstash/storage.rb', line 107 def initialize(folder, name) @base_path = folder @name = name # Avoid odd characters in paths, in case of issues with the file system safe_name = sanitize(@name) # Use a trie structure to avoid file system limits causing too many files in 1 folder # Downcase to avoid issues with case insensitive file systems trie_parents = safe_name[0...3].downcase.split("") # The digest is included in case the name differs only by case # Some file systems are case insensitive, so such collisions will be a problem digest = Digest::MD5.hexdigest(@name) child_folder = "#{safe_name}-#{digest}" @folder = File.join(@base_path, *trie_parents, child_folder) end |
Instance Attribute Details
#folder ⇒ Object (readonly)
Returns the value of attribute folder.
92 93 94 |
# File 'lib/gemstash/storage.rb', line 92 def folder @folder end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
92 93 94 |
# File 'lib/gemstash/storage.rb', line 92 def name @name end |
Instance Method Details
#content(key) ⇒ String
Fetch the content for the given key
. This will load and cache the properties and the content of the key
. The key
corresponds to the content
key provided to #save.
171 172 173 174 175 |
# File 'lib/gemstash/storage.rb', line 171 def content(key) @content ||= {} load(key) unless @content.include?(key) @content[key] end |
#delete(key) ⇒ Gemstash::Resource
Delete the content for the given key
. If the key
is the last one for this resource, the metadata properties will be deleted as well. The key
corresponds to the content
key provided to #save.
The resource will be reset afterwards, clearing any cached content or properties.
Does nothing if the key doesn’t #exist?.
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 |
# File 'lib/gemstash/storage.rb', line 244 def delete(key) return self unless exist?(key) begin File.delete(content_filename(key)) rescue => e log_error "Failed to delete stored content at #{content_filename(key)}", e, level: :warn end begin File.delete(properties_filename) unless content? rescue => e log_error "Failed to delete stored properties at #{properties_filename}", e, level: :warn end return self ensure reset end |
#exist?(key = nil) ⇒ Boolean
When key
is nil, this will test if this resource exists with any content. If a key
is provided, this will test that the resource exists with at least the given key
file. The key
corresponds to the content
key provided to #save.
129 130 131 132 133 134 135 |
# File 'lib/gemstash/storage.rb', line 129 def exist?(key = nil) if key File.exist?(properties_filename) && File.exist?(content_filename(key)) else File.exist?(properties_filename) && content? end end |
#properties ⇒ Hash
Fetch the metadata properties for this resource. The properties will be cached for future calls.
181 182 183 184 |
# File 'lib/gemstash/storage.rb', line 181 def properties load_properties @properties || {} end |
#property?(*keys) ⇒ Boolean
Check if the metadata properties includes the keys
. The keys
represent a nested path in the properties to check.
Examples:
resource = Gemstash::Storage.for("x").resource("y")
resource.save({ file: "content" }, foo: "one", bar: { baz: "qux" })
resource.has_property?(:foo) # true
resource.has_property?(:bar, :baz) # true
resource.has_property?(:missing) # false
resource.has_property?(:foo, :bar) # false
222 223 224 225 226 227 228 229 230 231 |
# File 'lib/gemstash/storage.rb', line 222 def property?(*keys) keys.inject(node: properties, result: true) do |memo, key| if memo[:result] memo[:result] = memo[:node].is_a?(Hash) && memo[:node].include?(key) memo[:node] = memo[:node][key] if memo[:result] end memo end[:result] end |
#save(content, properties = nil) ⇒ Gemstash::Resource
Save one or more files for this resource given by the content
hash. Metadata properties about the file(s) may be provided in the optional properties
parameter. The keys in the content hash correspond to the file name for this resource, while the values will be the content stored for that key.
Separate calls to save for the same resource will replace existing files, and add new ones. Properties on additional calls will be merged with existing properties. Nested hashes in properties will also be merged.
Examples:
Gemstash::Storage.for("foo").resource("bar").save(baz: "qux")
Gemstash::Storage.for("foo").resource("bar").save(baz: "one", qux: "two")
Gemstash::Storage.for("foo").resource("bar").save({ baz: "qux" }, meta: true)
156 157 158 159 160 161 162 163 |
# File 'lib/gemstash/storage.rb', line 156 def save(content, properties = nil) content.each do |key, value| save_content(key, value) end update_properties(properties) self end |
#update_properties(props) ⇒ Gemstash::Resource
Update the metadata properties of this resource. The props
will be merged with any existing properties. Nested hashes in the properties will also be merged.
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/gemstash/storage.rb', line 192 def update_properties(props) load_properties(true) deep_merge = proc do |_, old_value, new_value| if old_value.is_a?(Hash) && new_value.is_a?(Hash) old_value.merge(new_value, &deep_merge) else new_value end end props = properties.merge(props || {}, &deep_merge) save_properties(properties.merge(props || {})) self end |