Module: ZipCode::FR
- Defined in:
- lib/zipcode-fr.rb
Overview
TODO: factor index system out TODO: factor country-independent code out rubocop:disable Metrics/ModuleLength
Class Method Summary collapse
- .append_infixes(idx, pos, val, min_size: 1) ⇒ Object
- .append_match(idx, pos, val) ⇒ Object
- .append_prefixes(idx, pos, val, min_size: 1) ⇒ Object
- .append_word_prefixes(idx, pos, val) ⇒ Object
- .append_words(idx, pos, val) ⇒ Object
-
.appender(idx, key, mode) ⇒ Object
TODO: create an appender registry rubocop:disable Metrics/AbcSize rubocop:disable Metrics/MethodLength.
- .clean(row) ⇒ Object
- .complete(name, str, key = nil) ⇒ Object
- .data_source ⇒ Object
- .each_prefix(val, min_size: 1) ⇒ Object
- .each_suffix(val, min_size: 1) ⇒ Object
- .each_word(val, &block) ⇒ Object
- .index(name) ⇒ Object
- .index!(name, data, modes = nil, key: nil) ⇒ Object
- .load ⇒ Object
- .memsize_of_index(name) ⇒ Object
- .open ⇒ Object
- .read_at(*positions, count: 1) ⇒ Object
- .reader ⇒ Object
- .reader_options ⇒ Object
- .ready? ⇒ Boolean
- .row_clean(row) ⇒ Object
- .row_to_h(row) ⇒ Object
- .search(name, str, case_insensitive: true) ⇒ Object
Class Method Details
.append_infixes(idx, pos, val, min_size: 1) ⇒ Object
141 142 143 144 145 146 147 |
# File 'lib/zipcode-fr.rb', line 141 def append_infixes(idx, pos, val, min_size: 1) each_prefix(val, min_size: min_size) do |prefix| each_suffix(prefix, min_size: min_size) do |infix| idx[infix.hash] << pos end end end |
.append_match(idx, pos, val) ⇒ Object
104 105 106 |
# File 'lib/zipcode-fr.rb', line 104 def append_match(idx, pos, val) idx[val.hash] << pos end |
.append_prefixes(idx, pos, val, min_size: 1) ⇒ Object
121 122 123 |
# File 'lib/zipcode-fr.rb', line 121 def append_prefixes(idx, pos, val, min_size: 1) each_prefix(val, min_size: min_size) { |prefix| idx[prefix.hash] << pos } end |
.append_word_prefixes(idx, pos, val) ⇒ Object
114 115 116 117 118 |
# File 'lib/zipcode-fr.rb', line 114 def append_word_prefixes(idx, pos, val) each_word(val) do |word| each_prefix(word) { |prefix| idx[prefix.hash] << pos } end end |
.append_words(idx, pos, val) ⇒ Object
109 110 111 |
# File 'lib/zipcode-fr.rb', line 109 def append_words(idx, pos, val) each_word(val) { |w| idx[w.hash] << pos } end |
.appender(idx, key, mode) ⇒ Object
TODO: create an appender registry rubocop:disable Metrics/AbcSize rubocop:disable Metrics/MethodLength
88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/zipcode-fr.rb', line 88 def appender(idx, key, mode) case mode when :prefix -> (pos, record) { append_prefixes(idx, pos, record[key]) } when :infix -> (pos, record) { append_infixes(idx, pos, record[key]) } when :word -> (pos, record) { append_words(idx, pos, record[key]) } when :word_prefix -> (pos, record) { append_word_prefixes(idx, pos, record[key]) } else -> (pos, record) { append_match(idx, pos, record[key]) } end end |
.clean(row) ⇒ Object
55 56 57 |
# File 'lib/zipcode-fr.rb', line 55 def clean(row) row_to_h(row_clean(row)) end |
.complete(name, str, key = nil) ⇒ Object
182 183 184 185 |
# File 'lib/zipcode-fr.rb', line 182 def complete(name, str, key = nil) key ||= name search(name, str).map { |e| e[key] } end |
.data_source ⇒ Object
23 24 25 26 |
# File 'lib/zipcode-fr.rb', line 23 def data_source path = 'vendor/data/code_postaux_v201410.csv' File.(File.join(File.dirname(__FILE__), '..', path)) end |
.each_prefix(val, min_size: 1) ⇒ Object
131 132 133 |
# File 'lib/zipcode-fr.rb', line 131 def each_prefix(val, min_size: 1) min_size.upto(val.length) { |i| yield val[0...i] } end |
.each_suffix(val, min_size: 1) ⇒ Object
136 137 138 |
# File 'lib/zipcode-fr.rb', line 136 def each_suffix(val, min_size: 1) min_size.upto(val.length) { |i| yield val[-i..-1] } end |
.each_word(val, &block) ⇒ Object
126 127 128 |
# File 'lib/zipcode-fr.rb', line 126 def each_word(val, &block) val.split.each(&block) end |
.index(name) ⇒ Object
150 151 152 153 154 155 156 |
# File 'lib/zipcode-fr.rb', line 150 def index(name) if @indexes.key?(name) @indexes[name] else fail "no index named #{name.inspect}" end end |
.index!(name, data, modes = nil, key: nil) ⇒ Object
70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/zipcode-fr.rb', line 70 def index!(name, data, modes = nil, key: nil) key ||= name index = Hash.new { |h, k| h[k] = [] unless h.frozen? } modes = [modes] unless modes.is_a?(Enumerable) modes.each do |mode| data.each(&appender(index, key, mode)) end index.each { |_, v| v.uniq! } index.freeze @indexes[name] = index end |
.load ⇒ Object
12 13 14 15 16 17 |
# File 'lib/zipcode-fr.rb', line 12 def load # TODO: non-optimal, but not overly long either index!(:name, reader, [:word_prefix, :match]) index!(:zip, reader, :prefix) @loaded = true end |
.memsize_of_index(name) ⇒ Object
159 160 161 162 163 |
# File 'lib/zipcode-fr.rb', line 159 def memsize_of_index(name) require 'objspace' ObjectSpace.memsize_of(@indexes[name]) + @indexes[name].reduce(0) { |a, (_, v)| a + ObjectSpace.memsize_of(v) } end |
.open ⇒ Object
37 38 39 40 41 42 |
# File 'lib/zipcode-fr.rb', line 37 def open CSV.open(data_source, 'rb', ) do |csv| csv.take(1) # skip header manually to preserve tell() yield csv end end |
.read_at(*positions, count: 1) ⇒ Object
165 166 167 168 169 170 171 172 173 174 |
# File 'lib/zipcode-fr.rb', line 165 def read_at(*positions, count: 1) return enum_for(:read_at, *positions, count: count) unless block_given? open do |io| positions.each do |pos| io.seek(pos) io.take(count).each { |row| yield clean(row) } end end end |
.reader ⇒ Object
45 46 47 48 49 50 51 52 |
# File 'lib/zipcode-fr.rb', line 45 def reader return enum_for(:reader) unless block_given? open do |io| pos = io.tell io.each { |row| yield(pos, clean(row)); pos = io.tell } end end |
.reader_options ⇒ Object
29 30 31 32 33 34 |
# File 'lib/zipcode-fr.rb', line 29 def { col_sep: ';', encoding: 'ISO-8859-1', } end |
.ready? ⇒ Boolean
19 20 21 |
# File 'lib/zipcode-fr.rb', line 19 def ready? @loaded end |
.row_clean(row) ⇒ Object
60 61 62 |
# File 'lib/zipcode-fr.rb', line 60 def row_clean(row) row.map { |e| e.strip.encode('UTF-8') } end |
.row_to_h(row) ⇒ Object
65 66 67 |
# File 'lib/zipcode-fr.rb', line 65 def row_to_h(row) [:insee, :name, :zip, :alt_name].zip(row).to_h end |
.search(name, str, case_insensitive: true) ⇒ Object
177 178 179 180 |
# File 'lib/zipcode-fr.rb', line 177 def search(name, str, case_insensitive: true) str = str.upcase if case_insensitive read_at(*index(name)[str.hash]) end |