File: chainable.rb

package info (click to toggle)
ruby-image-processing 1.10.3-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,312 kB
  • sloc: ruby: 1,504; sh: 14; makefile: 4
file content (93 lines) | stat: -rw-r--r-- 2,996 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
module ImageProcessing
  # Implements a chainable interface for building processing options.
  module Chainable
    # Specify the source image file.
    def source(file)
      branch source: file
    end

    # Specify the output format.
    def convert(format)
      branch format: format
    end

    # Specify processor options applied when loading the image.
    def loader(**options)
      branch loader: options
    end

    # Specify processor options applied when saving the image.
    def saver(**options)
      branch saver: options
    end

    # Add multiple operations as a hash or an array.
    #
    #   .apply(resize_to_limit: [400, 400], strip: true)
    #   # or
    #   .apply([[:resize_to_limit, [400, 400]], [:strip, true])
    def apply(operations)
      operations.inject(self) do |builder, (name, argument)|
        if argument == true || argument == nil
          builder.send(name)
        elsif argument.is_a?(Array)
          builder.send(name, *argument)
        elsif argument.is_a?(Hash)
          builder.send(name, **argument)
        else
          builder.send(name, argument)
        end
      end
    end

    # Assume that any unknown method names an operation supported by the
    # processor. Add a bang ("!") if you want processing to be performed.
    def method_missing(name, *args, &block)
      return super if name.to_s.end_with?("?")
      return send(name.to_s.chomp("!"), *args, &block).call if name.to_s.end_with?("!")

      operation(name, *args, &block)
    end
    ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)

    # Add an operation defined by the processor.
    def operation(name, *args, &block)
      branch operations: [[name, args, *block]]
    end

    # Call the defined processing and get the result. Allows specifying
    # the source file and destination.
    def call(file = nil, destination: nil, **call_options)
      options = {}
      options = options.merge(source: file) if file
      options = options.merge(destination: destination) if destination

      branch(**options).call!(**call_options)
    end

    # Creates a new builder object, merging current options with new options.
    def branch(loader: nil, saver: nil, operations: nil, **other_options)
      options = respond_to?(:options) ? self.options : DEFAULT_OPTIONS

      options = options.merge(loader: options[:loader].merge(loader)) if loader
      options = options.merge(saver: options[:saver].merge(saver)) if saver
      options = options.merge(operations: options[:operations] + operations) if operations
      options = options.merge(processor: self::Processor) unless self.is_a?(Builder)
      options = options.merge(other_options)

      options.freeze

      Builder.new(options)
    end

    # Empty options which the builder starts with.
    DEFAULT_OPTIONS = {
      source:     nil,
      loader:     {},
      saver:      {},
      format:     nil,
      operations: [],
      processor:  nil,
    }.freeze
  end
end