Module: Uniword::LazyLoader

Included in:
Image
Defined in:
lib/uniword/lazy_loader.rb

Overview

Module for lazy loading attributes to reduce memory footprint.

Lazy loading delays the loading of data until it is actually needed, which helps reduce memory usage for large documents.

Examples:

Using lazy attributes

class Document
  extend LazyLoader

  lazy_attr :paragraphs do
    # Load paragraphs only when accessed
    parse_paragraphs_from_xml
  end
end

Instance Method Summary collapse

Instance Method Details

#lazy_attr(name, &loader) ⇒ void

This method returns an undefined value.

Define a lazy attribute that loads only when first accessed.

The loader block is executed once on first access, and the result is cached for subsequent accesses.

Examples:

Define a lazy attribute

lazy_attr :images do
  load_images_from_disk
end

Parameters:

  • name (Symbol)

    The attribute name

  • loader (Proc)

    Block that returns the attribute value

Raises:

  • (ArgumentError)


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
# File 'lib/uniword/lazy_loader.rb', line 32

def lazy_attr(name, &loader)
  raise ArgumentError, "Block required for lazy_attr" unless loader

  # Define getter method
  define_method(name) do
    instance_variable = "@#{name}"

    # Return cached value if already loaded
    return instance_variable_get(instance_variable) if instance_variable_defined?(instance_variable)

    # Load and cache the value
    value = instance_exec(&loader)
    instance_variable_set(instance_variable, value)
    value
  end

  # Define predicate method to check if loaded
  define_method("#{name}_loaded?") do
    instance_variable_defined?("@#{name}")
  end

  # Define method to clear cached value
  define_method("clear_#{name}") do
    remove_instance_variable("@#{name}") if instance_variable_defined?("@#{name}")
  end
end

#lazy_collection(name, &loader) ⇒ void

This method returns an undefined value.

Define a lazy collection attribute with batch loading.

Similar to lazy_attr but optimized for collections that can be loaded in batches or filtered on demand.

Examples:

Define a lazy collection

lazy_collection :tables do
  load_tables_from_xml
end

Parameters:

  • name (Symbol)

    The collection attribute name

  • loader (Proc)

    Block that returns the collection

Raises:

  • (ArgumentError)


72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/uniword/lazy_loader.rb', line 72

def lazy_collection(name, &loader)
  raise ArgumentError, "Block required for lazy_collection" unless loader

  # Define getter that returns array
  define_method(name) do
    instance_variable = "@#{name}"

    # Return cached collection if already loaded
    return instance_variable_get(instance_variable) if instance_variable_defined?(instance_variable)

    # Load and cache the collection
    collection = instance_exec(&loader)
    collection = [] if collection.nil?
    collection = Array(collection) unless collection.is_a?(Array)

    instance_variable_set(instance_variable, collection)
    collection
  end

  # Define method to check if collection is loaded
  define_method("#{name}_loaded?") do
    instance_variable_defined?("@#{name}")
  end

  # Define method to clear cached collection
  define_method("clear_#{name}") do
    remove_instance_variable("@#{name}") if instance_variable_defined?("@#{name}")
  end

  # Define method to get collection size without loading all items
  define_method("#{name}_count") do
    instance_variable = "@#{name}"
    return instance_variable_get(instance_variable).size if instance_variable_defined?(instance_variable)

    # If not loaded, try to get count without loading
    # This is a hook for subclasses to override
    send(name).size
  end
end