Class: ActsAsTable::Reader

Inherits:
Object
  • Object
show all
Defined in:
lib/acts_as_table/reader.rb

Overview

ActsAsTable reader object.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(row_model, input = $stdin, **options) {|reader| ... } ⇒ ActsAsTable::Reader

Returns a new ActsAsTable reader object using the given ActsAsTable row model, input stream and options.

Parameters:

Yield Parameters:

Yield Returns:

  • (void)


51
52
53
54
55
56
57
58
59
60
# File 'lib/acts_as_table/reader.rb', line 51

def initialize(row_model, input = $stdin, **options, &block)
  @row_model, @input, @options = row_model, input, options.dup

  if block_given?
    case block.arity
      when 1 then block.call(self)
      else self.instance_eval(&block)
    end
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args) {|*args, &block| ... } ⇒ Object

Delegates to the input stream for this ActsAsTable reader object.

Parameters:

  • method_name (String)
  • args (Array<Object>)

Yields:

  • (*args, &block)

Yield Returns:

  • (Object)

Returns:

  • (Object)

Raises:

  • (NoMethodError)


70
71
72
# File 'lib/acts_as_table/reader.rb', line 70

def method_missing(method_name, *args, &block)
  @input.respond_to?(method_name, false) ? @input.send(method_name, *args, &block) : super(method_name, *args, &block)
end

Instance Attribute Details

#inputIO (readonly)

Returns the input stream for this ActsAsTable reader object.

Returns:

  • (IO)


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
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
122
123
124
125
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
# File 'lib/acts_as_table/reader.rb', line 28

class Reader
  # Returns a new ActsAsTable reader object based on a symbolic name using the given arguments.
  #
  # @param [Symbol] format
  # @param [Array<Object>] args
  # @yieldparam [ActsAsTable::Reader] reader
  # @yieldreturn [void]
  # @return [ActsAsTable::Reader]
  # @raise [ArgumentError] If the given symbolic name is invalid.
  def self.for(format, *args, &block)
    ActsAsTable.for(format).reader(*args, &block)
  end

  attr_reader :row_model, :input, :options

  # Returns a new ActsAsTable reader object using the given ActsAsTable row model, input stream and options.
  #
  # @param [ActsAsTable::RowModel] row_model
  # @param [IO] input
  # @param [Hash<Symbol, Object>] options
  # @yieldparam [ActsAsTable::Reader] reader
  # @yieldreturn [void]
  # @return [ActsAsTable::Reader]
  def initialize(row_model, input = $stdin, **options, &block)
    @row_model, @input, @options = row_model, input, options.dup

    if block_given?
      case block.arity
        when 1 then block.call(self)
        else self.instance_eval(&block)
      end
    end
  end

  # Delegates to the input stream for this ActsAsTable reader object.
  #
  # @param [String] method_name
  # @param [Array<Object>] args
  # @yield [*args, &block]
  # @yieldreturn [Object]
  # @return [Object]
  # @raise [NoMethodError]
  def method_missing(method_name, *args, &block)
    @input.respond_to?(method_name, false) ? @input.send(method_name, *args, &block) : super(method_name, *args, &block)
  end

  # Delegates to the input stream for this ActsAsTable reader object.
  #
  # @param [String] method_name
  # @param [Boolean] include_all
  # @return [Boolean]
  def respond_to?(method_name, include_all = false)
    @input.respond_to?(method_name, false) || super(method_name, include_all)
  end

  # Returns a pair, where the first element is the headers and the second element is a flag that indicates if input stream is at end of file.
  #
  # @return [Array<Object>]
  # @raise [ActsAsTable::HeadersNotFound] If the headers are not found by this ActsAsTable reader object.
  # @raise [ActsAsTable::InvalidHeaders] If the headers do not match the ActsAsTable row model for this ActsAsTable reader object.
  def read_headers
    # @return [ActsAsTable::Headers::Array]
    headers = @row_model.to_headers

    # @return [Boolean]
    eof = false

    # @return [Array<Array<String>, nil>]
    rows = ::Array.new(headers.size) { |index|
      row, eof = *self.read_row

      unless row.nil?
        row += ::Array.new(headers[index].size - row.size) { nil }
      end

      row
    }

    if rows.any?(&:nil?)
      raise ActsAsTable::HeadersNotFound.new("#{self.class}#read_headers - must exist")
    end

    unless [headers, rows].transpose.all? { |pair| pair[0] == pair[1] }
      raise ActsAsTable::InvalidHeaders.new("#{self.class}#read_headers - invalid")
    end

    [rows, eof]
  end

  # Returns a pair, where the first element is the next row or +nil+ if input stream is at end of file and the second element indicates if input stream is at end of file.
  #
  # @return [Object]
  def read_row
    raise ::NotImplementedError.new("#{self.class}#read_row")
  end

  # Enumerates the rows in the input stream.
  #
  # @yieldparam [Array<String, nil>, nil] row
  # @yieldreturn [void]
  # @return [Enumerable<Array<String, nil>, nil>]
  # @raise [ActsAsTable::HeadersNotFound] If the headers are not found by this ActsAsTable reader object.
  # @raise [ActsAsTable::InvalidHeaders] If the headers do not match the ActsAsTable row model for this ActsAsTable reader object.
  def each_row(&block)
    ::Enumerator.new { |enumerator|
      headers, eof = *self.read_headers

      until eof
        row, eof = *self.read_row

        unless eof
          enumerator << row
        end
      end
    }.each(&block)
  end

  # Returns a new ActsAsTable table object by reading all rows in the input stream.
  #
  # @return [ActsAsTable::Table]
  # @raise [ActsAsTable::HeadersNotFound] If the headers are not found by this ActsAsTable reader object.
  # @raise [ActsAsTable::InvalidHeaders] If the headers do not match the ActsAsTable row model for this ActsAsTable reader object.
  # @raise [ArgumentError] If the name of a class for a given record does not match the class name for the corresponding ActsAsTable record model.
  def read_table
    ActsAsTable::Table.new do |table|
      table.row_model = @row_model

      self.each_row do |row|
        records = table.from_row(row)

        records.each do |record|
          record.position = self.lineno
        end
      end
    end
  end
end

#optionsHash<Symbol, Object> (readonly)

Returns the options for this ActsAsTable reader object.

Returns:

  • (Hash<Symbol, Object>)


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
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
122
123
124
125
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
# File 'lib/acts_as_table/reader.rb', line 28

class Reader
  # Returns a new ActsAsTable reader object based on a symbolic name using the given arguments.
  #
  # @param [Symbol] format
  # @param [Array<Object>] args
  # @yieldparam [ActsAsTable::Reader] reader
  # @yieldreturn [void]
  # @return [ActsAsTable::Reader]
  # @raise [ArgumentError] If the given symbolic name is invalid.
  def self.for(format, *args, &block)
    ActsAsTable.for(format).reader(*args, &block)
  end

  attr_reader :row_model, :input, :options

  # Returns a new ActsAsTable reader object using the given ActsAsTable row model, input stream and options.
  #
  # @param [ActsAsTable::RowModel] row_model
  # @param [IO] input
  # @param [Hash<Symbol, Object>] options
  # @yieldparam [ActsAsTable::Reader] reader
  # @yieldreturn [void]
  # @return [ActsAsTable::Reader]
  def initialize(row_model, input = $stdin, **options, &block)
    @row_model, @input, @options = row_model, input, options.dup

    if block_given?
      case block.arity
        when 1 then block.call(self)
        else self.instance_eval(&block)
      end
    end
  end

  # Delegates to the input stream for this ActsAsTable reader object.
  #
  # @param [String] method_name
  # @param [Array<Object>] args
  # @yield [*args, &block]
  # @yieldreturn [Object]
  # @return [Object]
  # @raise [NoMethodError]
  def method_missing(method_name, *args, &block)
    @input.respond_to?(method_name, false) ? @input.send(method_name, *args, &block) : super(method_name, *args, &block)
  end

  # Delegates to the input stream for this ActsAsTable reader object.
  #
  # @param [String] method_name
  # @param [Boolean] include_all
  # @return [Boolean]
  def respond_to?(method_name, include_all = false)
    @input.respond_to?(method_name, false) || super(method_name, include_all)
  end

  # Returns a pair, where the first element is the headers and the second element is a flag that indicates if input stream is at end of file.
  #
  # @return [Array<Object>]
  # @raise [ActsAsTable::HeadersNotFound] If the headers are not found by this ActsAsTable reader object.
  # @raise [ActsAsTable::InvalidHeaders] If the headers do not match the ActsAsTable row model for this ActsAsTable reader object.
  def read_headers
    # @return [ActsAsTable::Headers::Array]
    headers = @row_model.to_headers

    # @return [Boolean]
    eof = false

    # @return [Array<Array<String>, nil>]
    rows = ::Array.new(headers.size) { |index|
      row, eof = *self.read_row

      unless row.nil?
        row += ::Array.new(headers[index].size - row.size) { nil }
      end

      row
    }

    if rows.any?(&:nil?)
      raise ActsAsTable::HeadersNotFound.new("#{self.class}#read_headers - must exist")
    end

    unless [headers, rows].transpose.all? { |pair| pair[0] == pair[1] }
      raise ActsAsTable::InvalidHeaders.new("#{self.class}#read_headers - invalid")
    end

    [rows, eof]
  end

  # Returns a pair, where the first element is the next row or +nil+ if input stream is at end of file and the second element indicates if input stream is at end of file.
  #
  # @return [Object]
  def read_row
    raise ::NotImplementedError.new("#{self.class}#read_row")
  end

  # Enumerates the rows in the input stream.
  #
  # @yieldparam [Array<String, nil>, nil] row
  # @yieldreturn [void]
  # @return [Enumerable<Array<String, nil>, nil>]
  # @raise [ActsAsTable::HeadersNotFound] If the headers are not found by this ActsAsTable reader object.
  # @raise [ActsAsTable::InvalidHeaders] If the headers do not match the ActsAsTable row model for this ActsAsTable reader object.
  def each_row(&block)
    ::Enumerator.new { |enumerator|
      headers, eof = *self.read_headers

      until eof
        row, eof = *self.read_row

        unless eof
          enumerator << row
        end
      end
    }.each(&block)
  end

  # Returns a new ActsAsTable table object by reading all rows in the input stream.
  #
  # @return [ActsAsTable::Table]
  # @raise [ActsAsTable::HeadersNotFound] If the headers are not found by this ActsAsTable reader object.
  # @raise [ActsAsTable::InvalidHeaders] If the headers do not match the ActsAsTable row model for this ActsAsTable reader object.
  # @raise [ArgumentError] If the name of a class for a given record does not match the class name for the corresponding ActsAsTable record model.
  def read_table
    ActsAsTable::Table.new do |table|
      table.row_model = @row_model

      self.each_row do |row|
        records = table.from_row(row)

        records.each do |record|
          record.position = self.lineno
        end
      end
    end
  end
end

#row_modelActsAsTable::RowModel (readonly)

Returns the ActsAsTable row model for this ActsAsTable reader object.



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
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
122
123
124
125
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
# File 'lib/acts_as_table/reader.rb', line 28

class Reader
  # Returns a new ActsAsTable reader object based on a symbolic name using the given arguments.
  #
  # @param [Symbol] format
  # @param [Array<Object>] args
  # @yieldparam [ActsAsTable::Reader] reader
  # @yieldreturn [void]
  # @return [ActsAsTable::Reader]
  # @raise [ArgumentError] If the given symbolic name is invalid.
  def self.for(format, *args, &block)
    ActsAsTable.for(format).reader(*args, &block)
  end

  attr_reader :row_model, :input, :options

  # Returns a new ActsAsTable reader object using the given ActsAsTable row model, input stream and options.
  #
  # @param [ActsAsTable::RowModel] row_model
  # @param [IO] input
  # @param [Hash<Symbol, Object>] options
  # @yieldparam [ActsAsTable::Reader] reader
  # @yieldreturn [void]
  # @return [ActsAsTable::Reader]
  def initialize(row_model, input = $stdin, **options, &block)
    @row_model, @input, @options = row_model, input, options.dup

    if block_given?
      case block.arity
        when 1 then block.call(self)
        else self.instance_eval(&block)
      end
    end
  end

  # Delegates to the input stream for this ActsAsTable reader object.
  #
  # @param [String] method_name
  # @param [Array<Object>] args
  # @yield [*args, &block]
  # @yieldreturn [Object]
  # @return [Object]
  # @raise [NoMethodError]
  def method_missing(method_name, *args, &block)
    @input.respond_to?(method_name, false) ? @input.send(method_name, *args, &block) : super(method_name, *args, &block)
  end

  # Delegates to the input stream for this ActsAsTable reader object.
  #
  # @param [String] method_name
  # @param [Boolean] include_all
  # @return [Boolean]
  def respond_to?(method_name, include_all = false)
    @input.respond_to?(method_name, false) || super(method_name, include_all)
  end

  # Returns a pair, where the first element is the headers and the second element is a flag that indicates if input stream is at end of file.
  #
  # @return [Array<Object>]
  # @raise [ActsAsTable::HeadersNotFound] If the headers are not found by this ActsAsTable reader object.
  # @raise [ActsAsTable::InvalidHeaders] If the headers do not match the ActsAsTable row model for this ActsAsTable reader object.
  def read_headers
    # @return [ActsAsTable::Headers::Array]
    headers = @row_model.to_headers

    # @return [Boolean]
    eof = false

    # @return [Array<Array<String>, nil>]
    rows = ::Array.new(headers.size) { |index|
      row, eof = *self.read_row

      unless row.nil?
        row += ::Array.new(headers[index].size - row.size) { nil }
      end

      row
    }

    if rows.any?(&:nil?)
      raise ActsAsTable::HeadersNotFound.new("#{self.class}#read_headers - must exist")
    end

    unless [headers, rows].transpose.all? { |pair| pair[0] == pair[1] }
      raise ActsAsTable::InvalidHeaders.new("#{self.class}#read_headers - invalid")
    end

    [rows, eof]
  end

  # Returns a pair, where the first element is the next row or +nil+ if input stream is at end of file and the second element indicates if input stream is at end of file.
  #
  # @return [Object]
  def read_row
    raise ::NotImplementedError.new("#{self.class}#read_row")
  end

  # Enumerates the rows in the input stream.
  #
  # @yieldparam [Array<String, nil>, nil] row
  # @yieldreturn [void]
  # @return [Enumerable<Array<String, nil>, nil>]
  # @raise [ActsAsTable::HeadersNotFound] If the headers are not found by this ActsAsTable reader object.
  # @raise [ActsAsTable::InvalidHeaders] If the headers do not match the ActsAsTable row model for this ActsAsTable reader object.
  def each_row(&block)
    ::Enumerator.new { |enumerator|
      headers, eof = *self.read_headers

      until eof
        row, eof = *self.read_row

        unless eof
          enumerator << row
        end
      end
    }.each(&block)
  end

  # Returns a new ActsAsTable table object by reading all rows in the input stream.
  #
  # @return [ActsAsTable::Table]
  # @raise [ActsAsTable::HeadersNotFound] If the headers are not found by this ActsAsTable reader object.
  # @raise [ActsAsTable::InvalidHeaders] If the headers do not match the ActsAsTable row model for this ActsAsTable reader object.
  # @raise [ArgumentError] If the name of a class for a given record does not match the class name for the corresponding ActsAsTable record model.
  def read_table
    ActsAsTable::Table.new do |table|
      table.row_model = @row_model

      self.each_row do |row|
        records = table.from_row(row)

        records.each do |record|
          record.position = self.lineno
        end
      end
    end
  end
end

Class Method Details

.for(format, *args) {|reader| ... } ⇒ ActsAsTable::Reader

Returns a new ActsAsTable reader object based on a symbolic name using the given arguments.

Parameters:

  • format (Symbol)
  • args (Array<Object>)

Yield Parameters:

Yield Returns:

  • (void)

Returns:

Raises:

  • (ArgumentError)

    If the given symbolic name is invalid.



37
38
39
# File 'lib/acts_as_table/reader.rb', line 37

def self.for(format, *args, &block)
  ActsAsTable.for(format).reader(*args, &block)
end

Instance Method Details

#each_row {|row| ... } ⇒ Enumerable<Array<String, nil>, nil>

Enumerates the rows in the input stream.

Yield Parameters:

  • row (Array<String, nil>, nil)

Yield Returns:

  • (void)

Returns:

  • (Enumerable<Array<String, nil>, nil>)

Raises:



131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/acts_as_table/reader.rb', line 131

def each_row(&block)
  ::Enumerator.new { |enumerator|
    headers, eof = *self.read_headers

    until eof
      row, eof = *self.read_row

      unless eof
        enumerator << row
      end
    end
  }.each(&block)
end

#read_headersArray<Object>

Returns a pair, where the first element is the headers and the second element is a flag that indicates if input stream is at end of file.

Returns:

  • (Array<Object>)

Raises:



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
# File 'lib/acts_as_table/reader.rb', line 88

def read_headers
  # @return [ActsAsTable::Headers::Array]
  headers = @row_model.to_headers

  # @return [Boolean]
  eof = false

  # @return [Array<Array<String>, nil>]
  rows = ::Array.new(headers.size) { |index|
    row, eof = *self.read_row

    unless row.nil?
      row += ::Array.new(headers[index].size - row.size) { nil }
    end

    row
  }

  if rows.any?(&:nil?)
    raise ActsAsTable::HeadersNotFound.new("#{self.class}#read_headers - must exist")
  end

  unless [headers, rows].transpose.all? { |pair| pair[0] == pair[1] }
    raise ActsAsTable::InvalidHeaders.new("#{self.class}#read_headers - invalid")
  end

  [rows, eof]
end

#read_rowObject

Returns a pair, where the first element is the next row or +nil+ if input stream is at end of file and the second element indicates if input stream is at end of file.

Returns:

  • (Object)

Raises:

  • (::NotImplementedError)


120
121
122
# File 'lib/acts_as_table/reader.rb', line 120

def read_row
  raise ::NotImplementedError.new("#{self.class}#read_row")
end

#read_tableActsAsTable::Table

Returns a new ActsAsTable table object by reading all rows in the input stream.

Returns:

Raises:

  • (ActsAsTable::HeadersNotFound)

    If the headers are not found by this ActsAsTable reader object.

  • (ActsAsTable::InvalidHeaders)

    If the headers do not match the ActsAsTable row model for this ActsAsTable reader object.

  • (ArgumentError)

    If the name of a class for a given record does not match the class name for the corresponding ActsAsTable record model.



151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/acts_as_table/reader.rb', line 151

def read_table
  ActsAsTable::Table.new do |table|
    table.row_model = @row_model

    self.each_row do |row|
      records = table.from_row(row)

      records.each do |record|
        record.position = self.lineno
      end
    end
  end
end

#respond_to?(method_name, include_all = false) ⇒ Boolean

Delegates to the input stream for this ActsAsTable reader object.

Parameters:

  • method_name (String)
  • include_all (Boolean) (defaults to: false)

Returns:

  • (Boolean)


79
80
81
# File 'lib/acts_as_table/reader.rb', line 79

def respond_to?(method_name, include_all = false)
  @input.respond_to?(method_name, false) || super(method_name, include_all)
end