Class: Sablon::DOM::Relationships

Inherits:
FileHandler show all
Defined in:
lib/sablon/document_object_model/relationships.rb

Overview

Adds new relationships to the entry’s corresponding relationships file

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(xml_node) ⇒ Relationships

Sets up the class instance to handle new relationships for a document. I only care about tags that have an integer component



73
74
75
76
77
78
# File 'lib/sablon/document_object_model/relationships.rb', line 73

def initialize(xml_node)
  super
  #
  @relationships = xml_node.root
  @max_rid = max_attribute_value('Relationship', 'Id')
end

Class Method Details

.extend_model(model_klass) ⇒ Object

extends the Model class so it now has an “add_relationship” method



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
# File 'lib/sablon/document_object_model/relationships.rb', line 10

def self.extend_model(model_klass)
  super do
    #
    # adds a relationship to the rels file for the current entry
    define_method(:add_relationship) do |rel_attr|
      # detemine name of rels file to augment
      rels_name = Relationships.rels_entry_name_for(@current_entry)

      # create the file if needed and update DOM
      create_entry_if_not_exist(rels_name, Relationships.file_template)
      @dom[rels_name].add_relationship(rel_attr)
    end
    #
    # adds file to the /word/media folder without overwriting an
    # existing file
    define_method(:add_media) do |name, data, rel_attr|
      rel_attr[:Target] = "media/#{name}"
      # This matches any characters after the last "." in the filename
      unless (extension = name.match(/.+\.(.+?$)/).to_a[1])
        raise ArgumentError, "Filename: '#{name}' has no discernable extension"
      end
      type = rel_attr[:Type].match(%r{/(\w+?)$}).to_a[1] + "/#{extension}"
      #
      if @zip_contents["word/#{rel_attr[:Target]}"]
        names = @zip_contents.keys.map { |n| File.basename(n) }
        pattern = "^(\\d+)-#{name}"
        max_val = names.collect { |n| n.match(pattern).to_a[1].to_i }.max
        rel_attr[:Target] = "media/#{max_val + 1}-#{name}"
      end
      #
      # add the content to the zip and create the relationship
      @zip_contents["word/#{rel_attr[:Target]}"] = data
      add_content_type(extension, type)
      add_relationship(rel_attr)
    end
    #
    # locates an existing rId in the approprirate rels file
    define_method(:find_relationship_by) do |attribute, value, entry = nil|
      entry = @current_entry if entry.nil?
      # find the rels file and search it if it exists
      rels_name = Relationships.rels_entry_name_for(entry)
      return unless @dom[rels_name]
      #
      @dom[rels_name].find_relationship_by(attribute, value)
    end
  end
end

.file_templateObject



58
59
60
61
62
63
64
# File 'lib/sablon/document_object_model/relationships.rb', line 58

def self.file_template
  <<-XML.gsub(/^\s+|\n/, '')
    <?xml version="1.0" encoding="UTF-8"?>
    <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
    </Relationships>
  XML
end

.rels_entry_name_for(entry_name) ⇒ Object



66
67
68
69
# File 'lib/sablon/document_object_model/relationships.rb', line 66

def self.rels_entry_name_for(entry_name)
  par_dir = Pathname.new(File.dirname(entry_name))
  par_dir.join('_rels', "#{File.basename(entry_name)}.rels").to_s
end

Instance Method Details

#add_relationship(rel_attr) ⇒ Object

adds a new relationship and returns the corresponding rId for it



87
88
89
90
91
92
# File 'lib/sablon/document_object_model/relationships.rb', line 87

def add_relationship(rel_attr)
  rel_attr['Id'] = "rId#{next_rid}"
  @relationships << relationship_tag(rel_attr)
  #
  rel_attr['Id']
end

#find_relationship_by(attribute, value) ⇒ Object

Reurns an XML node based on the attribute value or nil if one does not exist



96
97
98
# File 'lib/sablon/document_object_model/relationships.rb', line 96

def find_relationship_by(attribute, value)
  @relationships.css(%(Relationship[#{attribute}="#{value}"])).first
end

#max_attribute_value(selector, attr_name) ⇒ Object

Finds the maximum value of an attribute by converting it to an integer. Non numeric portions of values are ignored.



82
83
84
# File 'lib/sablon/document_object_model/relationships.rb', line 82

def max_attribute_value(selector, attr_name)
  super(@relationships, selector, attr_name, query_method: :css)
end