Class: Gemstash::Resource
- Inherits:
-
Object
- Object
- Gemstash::Resource
- Includes:
- 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.
104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/gemstash/storage.rb', line 104 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.
89 90 91 |
# File 'lib/gemstash/storage.rb', line 89 def folder @folder end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
89 90 91 |
# File 'lib/gemstash/storage.rb', line 89 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.
168 169 170 171 172 |
# File 'lib/gemstash/storage.rb', line 168 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?.
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
# File 'lib/gemstash/storage.rb', line 241 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.
126 127 128 129 130 131 132 |
# File 'lib/gemstash/storage.rb', line 126 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.
178 179 180 181 |
# File 'lib/gemstash/storage.rb', line 178 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
219 220 221 222 223 224 225 226 227 228 |
# File 'lib/gemstash/storage.rb', line 219 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)
153 154 155 156 157 158 159 160 |
# File 'lib/gemstash/storage.rb', line 153 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.
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
# File 'lib/gemstash/storage.rb', line 189 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 |