Class: Alf::Reader

Inherits:
Object
  • Object
show all
Extended by:
Support::Registry
Includes:
Enumerable
Defined in:
lib/alf/reader.rb,
lib/alf/reader/csv.rb,
lib/alf/reader/rash.rb,
lib/alf/reader/ruby.rb,
lib/alf/reader/json.rb,
lib/alf/reader/yaml.rb

Overview

Implements an iterator at the interface with the outside world.

This base class provides a default behavior for readers that works with IO objects. It can be safely extended, overriden, or mimiced. This class also provides a registration mechanism to help getting Reader instances for specific file extensions. A typical scenario for using this registration mechanism is as follows:

# Registers a reader kind named :foo, associated with ".foo" file
# extensions and the FooFileDecoder class (typically a subclass of
# Reader)
Reader.register(:foo, [".foo"], FooFileDecoder)

# Later on, you can request a reader instance for a .foo file
r = Reader.reader('/a/path/to/a/file.foo')

# Also, a factory method is automatically installed on the Reader class
# itself. This factory method can be used with a String, or an IO object.
r = Reader.foo([a path or a IO object])

Direct Known Subclasses

CSV, JSON, Rash, Ruby, YAML

Defined Under Namespace

Classes: CSV, JSON, Rash, Ruby, YAML

Constant Summary collapse

DEFAULT_OPTIONS =

Default reader options

{}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Support::Registry

listen, listeners, register, registered

Constructor Details

#initialize(input, options = {}) ⇒ Reader

Creates a reader instance.

Parameters:

  • path (String or IO)

    to a file or IO object for input

  • options (Hash) (defaults to: {})

    Reader's options (see doc of subclasses)


114
115
116
117
118
# File 'lib/alf/reader.rb', line 114

def initialize(input, options = {})
  @input   = input
  @path    = Path(@input)
  @options = self.class.const_get(:DEFAULT_OPTIONS).merge(options)
end

Instance Attribute Details

#inputString, ...

Returns Input as initially provided to initialize

Returns:

  • (String, IO, ...)

    Input as initially provided to initialize


102
103
104
# File 'lib/alf/reader.rb', line 102

def input
  @input
end

#optionsHash

Returns Reader's options

Returns:

  • (Hash)

    Reader's options


108
109
110
# File 'lib/alf/reader.rb', line 108

def options
  @options
end

#pathObject (readonly)

Returns the value of attribute path


105
106
107
# File 'lib/alf/reader.rb', line 105

def path
  @path
end

Class Method Details

.by_mime_type(mime_type, *args) ⇒ Renderer

Returns a Reader instance for the given mime type.

Parameters:

  • mime_type (String)

    a given (simplified) MIME type

  • args (...)

    other arguments to pass to the reader constructor

Returns:

  • (Renderer)

    a Renderer instance, already wired if args are provided


78
79
80
81
82
83
84
# File 'lib/alf/reader.rb', line 78

def by_mime_type(mime_type, *args)
  if r = registered.find{|_,_,c| c.mime_type == mime_type}
    r.last.new(*args)
  else
    raise UnsupportedMimeTypeError, "No reader for `#{mime_type}`"
  end
end

.coerce(arg) ⇒ Object

Coerces `arg` to a Reader instance.

Parameters:

  • arg (Object)

    any value coercable to a Reader instance


63
64
65
66
67
68
69
70
# File 'lib/alf/reader.rb', line 63

def coerce(arg)
  case arg
  when Reader       then arg
  when IO, StringIO then rash(arg)
  else
    raise ArgumentError, "Unable to coerce `#{arg}` to a reader"
  end
end

.reader(source, *args) ⇒ Reader

Returns a Reader on `source` denoting a physical representation of a relation.

Parameters:

  • source (...)

    a String, a Path or an IO denoting a relation physical source.

  • args (Array)

    optional reader arguments

Returns:

  • (Reader)

    a reader instance built from arguments

Raises:

  • (ArgumentError)

    if `source` is not recognized or no reader can be found.


50
51
52
53
54
55
56
57
58
# File 'lib/alf/reader.rb', line 50

def reader(source, *args)
  if Path.like?(source)
    has_reader_for_ext!(Path(source).extname).new(source, *args)
  elsif args.empty?
    coerce(source)
  else
    raise ArgumentError, "Unable to return a reader for `#{source}`"
  end
end

.register(name, extensions, clazz) ⇒ Object

Registers a reader class associated with specific file extensions.

Registered class must provide a constructor with the following signature `new(path_or_io, connection = nil, options = {})`. The registration name must be a symbol which can safely be used as a ruby method name. A factory method of that name and signature is automatically installed on the Reader class.

Parameters:

  • name (Symbol)

    a name for the kind of data decoded

  • extensions (Array)

    file extensions mapped to the registered reader class (should include the '.', e.g. '.foo')

  • class (Class)

    Reader subclass used to decode this kind of files


39
40
41
# File 'lib/alf/reader.rb', line 39

def register(name, extensions, clazz)
  super([name, extensions, clazz], Reader)
end

Instance Method Details

#eachObject

Yields each tuple in turn

yields the block with line2tuple(line) on each of them. This method may be overriden if this behavior does not fit reader's needs.


125
126
127
128
129
130
131
# File 'lib/alf/reader.rb', line 125

def each
  return to_enum unless block_given?
  each_input_line do |line|
    tuple = line2tuple(line)
    yield tuple unless tuple.nil?
  end
end

#to_sObject

Returns a string representation


134
135
136
# File 'lib/alf/reader.rb', line 134

def to_s
  "#{self.class.name}(#{Path(input_path).basename || '...'})"
end