Module: Athena::Formats
- Defined in:
- lib/athena/formats.rb,
lib/athena/formats/dbm.rb,
lib/athena/formats/sql.rb,
lib/athena/formats/xml.rb,
lib/athena/formats/lingo.rb,
lib/athena/formats/sisis.rb,
lib/athena/formats/ferret.rb
Overview
In order to support additional input and/or output formats, Athena::Formats::Base needs to be sub-classed and an instance method parse or an instance method convert supplied, respectively. This way, a specific format can even function as both input and output format.
Defining custom formats
Define one or more classes that inherit from Athena::Formats::Base and either call Athena::Formats.register with your format class as parameter or call Athena::Formats.register_all with your surrounding namespace (which will then recursively add any format definitions below it). Alternatively, you can call Athena::Formats::Base.register_format at the end of your class definition to register just this class.
The directions supported by your custom format are determined automatically; see below for further details.
Defining an input format
An input format must provide a public instance method parse that accepts an input object (usually an IO object) and a block it passes each record (Athena::Record) to. See Athena::Formats::Base#parse.
Defining an output format
An output format must provide a public instance method convert that accepts a record (Athena::Record) and either returns a suitable value for output or writes the output itself. See Athena::Formats::Base#convert.
Aliases
In order to provide an alias name for a format, simply assign the format class to a new constant. Then you need to call Athena::Formats.register(your_new_const) to register your alias.
Defined Under Namespace
Classes: Base, ConfigError, DBM, DirectionMismatchError, DuplicateFormatDefinitionError, Ferret, FormatError, FormatNotFoundError, IllegalRecordElementError, Lingo, MYSQL, MySQL, NoRecordElementError, PGSQL, PgSQL, Sisis, XML
Constant Summary collapse
- CRLF =
CR+LF line ending.
%Q{\015\012}- CRLF_RE =
Regular expression to match (multiple) CR+LF line endings.
%r{(?:\r?\n)+}- METHODS =
Mapping of format direction to method required for implementation.
{ :in => 'parse', :out => 'convert' }
- Midos =
DBM
Class Attribute Summary collapse
-
.formats ⇒ Object
readonly
Container for registered formats per direction.
Class Method Summary collapse
-
.[](direction, format, *args) ⇒ Object
call-seq: Athena::Formats[direction, format, *args] -> aFormat.
-
.find(direction, format, instance = false) ⇒ Object
call-seq: Athena::Formats.find(direction, format) -> aFormatClass.
-
.format_name(fn) ⇒ Object
call-seq: Athena::Formats.format_name(name) -> aString.
-
.register(klass, name = nil, relax = false) ⇒ Object
call-seq: Athena::Formats.register(klass, name = nil, relax = false) -> anArray | nil.
-
.register_all(klass = self, registered = []) ⇒ Object
call-seq: Athena::Formats.register_all(klass = self) -> anArray.
-
.valid_format?(direction, format) ⇒ Boolean
call-seq: Athena::Formats.valid_format?(direction, format) -> true | false.
Class Attribute Details
.formats ⇒ Object (readonly)
Container for registered formats per direction. Use ::find or ::[] to access them.
89 90 91 |
# File 'lib/athena/formats.rb', line 89 def formats @formats end |
Class Method Details
.[](direction, format, *args) ⇒ Object
call-seq:
Athena::Formats[direction, format, *args] -> aFormat
Retrieves the format for direction by its name format (see ::find) and initializes it with args (see Base#init). Returns format unaltered if it already is a format instance, while making sure that it supports direction.
98 99 100 101 |
# File 'lib/athena/formats.rb', line 98 def [](direction, format, *args) res = find(direction, format, true) res.is_a?(Base) ? res : res.init(direction, *args) end |
.find(direction, format, instance = false) ⇒ Object
call-seq:
Athena::Formats.find(direction, format) -> aFormatClass
Retrieves the format for direction by its name format. Returns format‘s class if it already is a format instance, while making sure that it supports direction.
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 |
# File 'lib/athena/formats.rb', line 109 def find(direction, format, instance = false) directions = formats.keys unless directions.include?(direction) raise ArgumentError, "invalid direction: #{direction.inspect}" << " (must be one of: #{directions.map { |d| d.inspect }.join(', ')})" end case format when Symbol find(direction, format.to_s) when String formats[direction][format] or raise FormatNotFoundError.new(direction, format) else klass = format.class if klass < Base && !(directions = klass.directions).empty? if klass.has_direction?(direction) return instance ? format : klass else raise DirectionMismatchError.new(direction, directions) end else raise ArgumentError, "invalid format of type #{klass}" << " (expected one of: Symbol, String, or sub-class of #{Base})" end end end |
.format_name(fn) ⇒ Object
call-seq:
Athena::Formats.format_name(name) -> aString
Formats name as suitable format name.
214 215 216 217 218 |
# File 'lib/athena/formats.rb', line 214 def format_name(fn) fn.sub(/\A#{self}::/, ''). gsub(/([a-z\d])(?=[A-Z])/, '\1_'). gsub(/::/, '/').downcase end |
.register(klass, name = nil, relax = false) ⇒ Object
call-seq:
Athena::Formats.register(klass, name = nil, relax = false) -> anArray | nil
Registers klass as format under name (defaults to Base.format). Only warns instead of raising any errors when relax is true. Returns an array of the actual name klass has been registered under and the directions supported; returns nil if nothing has been registered.
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/athena/formats.rb', line 161 def register(klass, name = nil, relax = false) unless klass < Base return if relax raise ArgumentError, "must be a sub-class of #{Base}" end name = name ? name.to_s : klass.format methods = klass.public_instance_methods(false).map { |m| m.to_s } directions = klass.directions METHODS.each { |direction, method| next unless methods.include?(method) if formats[direction].has_key?(name) err = DuplicateFormatDefinitionError.new(direction, name) raise err unless relax warn err next else directions << direction unless klass.has_direction?(direction) formats[direction][name] = klass end } [name, directions] unless directions.empty? end |
.register_all(klass = self, registered = []) ⇒ Object
call-seq:
Athena::Formats.register_all(klass = self) -> anArray
Recursively registers all formats below klass (see ::register). Returns an array of all registered format names with their supported directions.
195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
# File 'lib/athena/formats.rb', line 195 def register_all(klass = self, registered = []) names = klass.constants names -= klass.superclass.constants if klass.is_a?(Class) names.each { |name| const = klass.const_get(name) next unless const.is_a?(Module) registered << register(const, format_name("#{klass}::#{name}"), true) register_all(const, registered) } registered.compact end |
.valid_format?(direction, format) ⇒ Boolean
call-seq:
Athena::Formats.valid_format?(direction, format) -> true | false
Indicates whether the direction/format combination is supported, i.e. a format by name format has been registered and supports direction.
145 146 147 148 149 150 151 |
# File 'lib/athena/formats.rb', line 145 def valid_format?(direction, format) if format.class < Base format.class.has_direction?(direction) else formats[direction].has_key?(format.to_s) end end |