Class: Importer::Sheet

Inherits:
Object
  • Object
show all
Defined in:
lib/iron/import/sheet.rb

Overview

The Sheet class handles building the sheet’s column configuration and other setup, then holds all load-time row data.

Defined Under Namespace

Classes: Data

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(importer, id) ⇒ Sheet

Returns a new instance of Sheet.



27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/iron/import/sheet.rb', line 27

def initialize(importer, id)
  @importer = importer
  @id = id

  @headerless = false
  @start_row = nil
  @filter = nil
  
  @columns = []
  
  reset
end

Instance Attribute Details

#columnsObject (readonly)

Returns the value of attribute columns.



18
19
20
# File 'lib/iron/import/sheet.rb', line 18

def columns
  @columns
end

#dataObject (readonly)

Returns the value of attribute data.



19
20
21
# File 'lib/iron/import/sheet.rb', line 19

def data
  @data
end

#importerObject (readonly)

Key data



17
18
19
# File 'lib/iron/import/sheet.rb', line 17

def importer
  @importer
end

Instance Method Details

#add_row(line, raw_data) ⇒ Object

Add a new row to our stash



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
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/iron/import/sheet.rb', line 85

def add_row(line, raw_data)
  # Add the row
  row = Row.new(self, line)
  
  # Parse out the values
  values = {}
  @columns.each do |col|
    index = col.data.index
    raw_val = raw_data[index]
    if col.parse
      val = col.parse_value(row, raw_val)
    else
      val = @importer.data.parse_value(raw_val, col.type)
    end
    values[col.key] = val
  end

  # Set the values and filter if needed
  row.set_values(values)
  return nil unless !@filter || @filter.call(row)
  
  # Row is solid, now check for missing required vals
  @columns.each do |col|
    val = values[col.key]
    if col.validate_value(row, val)
      if col.required?
        if values[col.key].nil?
          @importer.add_error(row, "Missing required value for #{col}")
        end
      end
    end
  end
  
  # We is good
  @data.rows << row
  row
end

#build(&block) ⇒ Object



40
41
42
# File 'lib/iron/import/sheet.rb', line 40

def build(&block)
  DslProxy.exec(self, &block)
end

#column(key, &block) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
# File 'lib/iron/import/sheet.rb', line 54

def column(key, &block)
  col = @columns.detect {|c| c.key == key }
  unless col
    col = Column.new(self, key)
    @columns << col
  end
  
  DslProxy::exec(col, &block) if block
  
  col
end

#dumpObject



180
181
182
# File 'lib/iron/import/sheet.rb', line 180

def dump
  @data.rows.collect(&:values)
end

#match_sheet?(name, index) ⇒ Boolean

Returns:

  • (Boolean)


168
169
170
171
172
173
174
# File 'lib/iron/import/sheet.rb', line 168

def match_sheet?(name, index)
  if @id.is_a?(Fixnum)
    @id.to_i == index+1
  else
    @id.to_s == name
  end
end

#parse_header(raw_rows) ⇒ Object

Process the raw values for the first rows in a sheet, and attempt to build a map of the column layout, and detect the first row of real data



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/iron/import/sheet.rb', line 126

def parse_header(raw_rows)
  if headerless?
    # Use implicit or explicit column position when told to not look for a header
    next_index = 0
    @columns.each do |col|
      if col.index.present?
        next_index = col.index
      end
      col.data.index = next_index
      next_index += 1
    end
    @data.start_row = @start_row || 1
    return true
    
  else
    # Match by testing
    raw_rows.each_with_index do |row, i|
      # Set up for this iteration
      remaining = @columns.dup
  
      # Step through this row's raw values, and look for a matching column for all columns
      row.each_with_index do |val, i|
        col = remaining.detect {|c| c.match_header?(val.to_s, i) }
        if col
          remaining -= [col]
          col.data.index = i
        end
      end
      
      if remaining.empty?
        # Found the cols, have a map, update our start row to be the next line and return!
        @data.start_row = @start_row || i+2
        return true
      end
    end
    
    # If we get here, we're hosed
    @importer.add_error(self, "Unable to locate required column header(s) in sheet")
    false
  end
end

#parse_raw_data(raw_rows) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/iron/import/sheet.rb', line 71

def parse_raw_data(raw_rows)
  # Find our column layout, start of data, etc
  if parse_header(raw_rows)
    # Now, run all the data and add it as a Row instance
    raw_rows.each_with_index do |raw, index|
      line = index + 1
      if line >= @data.start_row
        add_row(line, raw)
      end
    end
  end
end

#processObject



44
45
46
47
48
49
50
51
52
# File 'lib/iron/import/sheet.rb', line 44

def process
  @data.rows.each do |row|
    begin
      yield row
    rescue Exception => e
      @importer.add_error(row, e.to_s)
    end
  end
end

#resetObject

Reset for load attempt



67
68
69
# File 'lib/iron/import/sheet.rb', line 67

def reset
  @data = Data.new
end

#to_sObject



176
177
178
# File 'lib/iron/import/sheet.rb', line 176

def to_s
  "Sheet #{@id}"
end