Class: Cooltrainer::Change
- Inherits:
-
Struct
- Object
- Struct
- Cooltrainer::Change
- Defined in:
- lib/distorted/element_of_media/change.rb
Overview
Struct to encapsulate all the data needed to perform one (1) MIME::Type transformation of a source media file into any supported MIME::Type, possibly even the same type as input.
Instance Attribute Summary collapse
-
#atoms ⇒ Object
Returns the value of attribute atoms.
-
#basename ⇒ Object
Returns the value of attribute basename.
-
#breaks ⇒ Object
Returns the value of attribute breaks.
-
#molecule ⇒ Object
Returns the value of attribute molecule.
-
#src ⇒ Object
Returns the value of attribute src.
-
#tag ⇒ Object
Returns the value of attribute tag.
-
#type ⇒ Object
Returns the value of attribute type.
Instance Method Summary collapse
- #dig(*keys) ⇒ Object
-
#extname ⇒ Object
Returns the Change Type’s :preferred_extension as a String with leading dot (.).
-
#initialize(type, src: nil, molecule: nil, tag: nil, breaks: Array.new, **atoms) ⇒ Change
constructor
Customize the destination filename and other values before doing the normal Struct setup.
-
#method_missing(meth, *a, **k, &b) ⇒ Object
Support setting Atoms that were not defined at instantiation.
-
#name ⇒ Object
Returns a String describing the :names but rolled into one, e.g.
-
#names ⇒ Object
Returns an Array of filenames this Change should generate, one ‘full’/‘original’ plus any limit-breaks, e.g.
-
#path(dest_root, break_value) ⇒ Object
Returns a String absolute destination path for only one limit-break.
-
#paths(dest_root = ''.freeze) ⇒ Object
Returns an Array of all absolute destination paths this Change should generate, given a root destination directory.
-
#to_h ⇒ Object
Struct#to_h does exist in stdlib, but redefine its behavior to match our ‘:to_hash`.
-
#to_hash ⇒ Object
A generic version of Struct#to_hash was rejected with good reason, but I’m going to use it here because I want the implicit Struct-to-Hash conversion to let me destructure these Structs with a double-splat: bugs.ruby-lang.org/issues/4862.
Constructor Details
#initialize(type, src: nil, molecule: nil, tag: nil, breaks: Array.new, **atoms) ⇒ Change
Customize the destination filename and other values before doing the normal Struct setup.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/distorted/element_of_media/change.rb', line 17 def initialize(type, src: nil, molecule: nil, tag: nil, breaks: Array.new, **atoms) # `name` might have a leading slash if referenced as an absolute path as the Tag. basename = File.basename(src, '.*'.freeze).reverse.chomp('/'.freeze).reverse # Set the &default_proc on the kwarg-glob Hash instead of making a new Hash, atoms.default_proc = lambda { |h,k| h[k] = Cooltrainer::Atom.new } atoms.transform_values { # We might get Atoms already instantiated, but do it for any that aren't. # We won't have a default value for them in that case. |v| v.is_a?(Cooltrainer::Atom) ? atom : Cooltrainer::Atom.new(v, nil) }.each_key { |k| # Define accessors for context-specific :atoms keys/values that aren't normal Struct members. self.singleton_class.define_method(k) { self[:atoms]&.fetch(k, nil)&.get } self.singleton_class.define_method("#{k}=".to_sym) { |v| self[:atoms][k] = v } } # And now back to your regularly-scheduled Struct super(type: type, src: src, basename: basename, molecule: molecule, tag: tag, breaks: breaks, atoms: atoms) end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(meth, *a, **k, &b) ⇒ Object
Support setting Atoms that were not defined at instantiation.
95 96 97 98 99 100 101 102 103 |
# File 'lib/distorted/element_of_media/change.rb', line 95 def method_missing(meth, *a, **k, &b) # Are we a setter? if meth.to_s[-1] == '='.freeze # Set the :value of an existing Atom Struct self[:atoms][meth.to_s.chomp('='.freeze).to_sym].value = a.first else self[:atoms]&.fetch(meth, nil) end end |
Instance Attribute Details
#atoms ⇒ Object
Returns the value of attribute atoms
14 15 16 |
# File 'lib/distorted/element_of_media/change.rb', line 14 def atoms @atoms end |
#basename ⇒ Object
Returns the value of attribute basename
14 15 16 |
# File 'lib/distorted/element_of_media/change.rb', line 14 def basename @basename end |
#breaks ⇒ Object
Returns the value of attribute breaks
14 15 16 |
# File 'lib/distorted/element_of_media/change.rb', line 14 def breaks @breaks end |
#molecule ⇒ Object
Returns the value of attribute molecule
14 15 16 |
# File 'lib/distorted/element_of_media/change.rb', line 14 def molecule @molecule end |
#src ⇒ Object
Returns the value of attribute src
14 15 16 |
# File 'lib/distorted/element_of_media/change.rb', line 14 def src @src end |
#tag ⇒ Object
Returns the value of attribute tag
14 15 16 |
# File 'lib/distorted/element_of_media/change.rb', line 14 def tag @tag end |
#type ⇒ Object
Returns the value of attribute type
14 15 16 |
# File 'lib/distorted/element_of_media/change.rb', line 14 def type @type end |
Instance Method Details
#dig(*keys) ⇒ Object
92 |
# File 'lib/distorted/element_of_media/change.rb', line 92 def dig(*keys); self.to_hash.dig(*keys); end |
#extname ⇒ Object
Returns the Change Type’s :preferred_extension as a String with leading dot (.)
38 39 40 41 42 43 |
# File 'lib/distorted/element_of_media/change.rb', line 38 def extname @extname ||= begin dot = '.'.freeze unless type.preferred_extension.nil? || type.preferred_extension&.empty? "#{dot}#{type.preferred_extension}" end end |
#name ⇒ Object
Returns a String describing the :names but rolled into one, e.g. “IIDX-turntable-(400|800|1500).png”
57 58 59 60 |
# File 'lib/distorted/element_of_media/change.rb', line 57 def name = self[:breaks].length > 1 ? "-(#{self[:breaks].join('|'.freeze)})" : ''.freeze "#{self.basename}#{}#{self.extname}" end |
#names ⇒ Object
Returns an Array of filenames this Change should generate, one ‘full’/‘original’ plus any limit-breaks, e.g. [“DistorteD.png”, “DistorteD-333.png”, “DistorteD-555.png”, “DistorteD-888.png”, “DistorteD-1111.png”]
48 49 50 51 52 53 |
# File 'lib/distorted/element_of_media/change.rb', line 48 def names Array[''.freeze].concat(self[:breaks]).map { |b| filetag = (b.nil? || b&.to_s.empty?) ? ''.freeze : '-'.concat(b.to_s) "#{self[:basename]}#{"-#{self.tag}" unless self.tag.nil?}#{filetag}#{extname}" } end |
#path(dest_root, break_value) ⇒ Object
Returns a String absolute destination path for only one limit-break.
70 71 72 73 |
# File 'lib/distorted/element_of_media/change.rb', line 70 def path(dest_root, break_value) output_dir = self[:atoms]&.fetch(:dir, ''.freeze) return File.join(File.(dest_root), output_dir, "#{self.basename}#{"-#{self.tag}" unless self.tag.nil?}-#{break_value}#{self.extname}") end |
#paths(dest_root = ''.freeze) ⇒ Object
Returns an Array of all absolute destination paths this Change should generate, given a root destination directory.
64 65 66 67 |
# File 'lib/distorted/element_of_media/change.rb', line 64 def paths(dest_root = ''.freeze) # Empty String will expand to current working directory output_dir = self[:atoms]&.fetch(:dir, ''.freeze) return self.names.map { |n| File.join(File.(dest_root), output_dir, n) } end |
#to_h ⇒ Object
Struct#to_h does exist in stdlib, but redefine its behavior to match our ‘:to_hash`.
89 90 91 |
# File 'lib/distorted/element_of_media/change.rb', line 89 def to_h # Explicit Hash[self.members.reject{|m| m == :atoms}.zip(self.values.reject{|v| v.is_a?(Hash)})].merge(self[:atoms].transform_values(&:get)) end |
#to_hash ⇒ Object
A generic version of Struct#to_hash was rejected with good reason, but I’m going to use it here because I want the implicit Struct-to-Hash conversion to let me destructure these Structs with a double-splat: bugs.ruby-lang.org/issues/4862
Defining this method causes Ruby 2.7 to emit a “Using the last argument as keyword parameters is deprecated” warning if this Struct is passed to a method as the final positional argument! Ruby 2.7 will actually do the conversion when calling the method in that scenario, causing incorrect behavior to methods expecting Struct. This is why DD-Floor’s ‘:write` and DD-Jekyll’s ‘:render_to_output_buffer` pass an empty kwargs Hash. www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/
85 86 87 |
# File 'lib/distorted/element_of_media/change.rb', line 85 def to_hash # Implicit Hash[self.members.reject{|m| m == :atoms}.zip(self.values.reject{|v| v.is_a?(Hash)})].merge(self[:atoms].transform_values(&:get)) end |