class Lingo::Database
Constants
- BACKENDS
- BACKEND_BY_EXT
- FLD_SEP
- KEY_REF
- KEY_REF_RE
- SYS_KEY
Attributes
backend[R]
config[R]
lingo[R]
Public Class Methods
backend_by_ext(file, ext = File.extname(file))
click to toggle source
# File lib/lingo/database.rb, line 62 def backend_by_ext(file, ext = File.extname(file)) get_backend(BACKEND_BY_EXT[ext], file) or raise BackendNotFoundError.new(file) end
find_backend(env = 'LINGO_BACKEND')
click to toggle source
# File lib/lingo/database.rb, line 67 def find_backend(env = 'LINGO_BACKEND') env && get_backend(ENV[env]) || BACKENDS.find { |name| backend = get_backend(name, nil, true) and return backend } end
get_backend(name, file = nil, relax = false)
click to toggle source
# File lib/lingo/database.rb, line 72 def get_backend(name, file = nil, relax = false) return unless name Object.const_get(name) const_get("#{name}Store") rescue TypeError, NameError => err raise BackendNotAvailableError.new(name, file, err) unless relax end
new(id, lingo)
click to toggle source
# File lib/lingo/database.rb, line 87 def initialize(id, lingo) @id, @lingo, @config, @db = id, lingo, lingo.database_config(id), nil @val, @crypt, @srcfile = Hash.array, config.key?('crypt'), Lingo.find(:dict, config['name'], relax: true) begin @stofile = Lingo.find(:store, @srcfile) FileUtils.mkdir_p(File.dirname(@stofile)) rescue SourceFileNotFoundError => err @stofile = skip_ext = err.id backend = self.class.backend_by_ext(@stofile) unless err.name rescue NoWritableStoreError backend = HashStore end extend(@backend = backend || self.class.find_backend || HashStore) @stofile << store_ext unless skip_ext || !respond_to?(:store_ext) convert unless uptodate? end
open(*args, &block)
click to toggle source
# File lib/lingo/database.rb, line 81 def open(*args, &block) new(*args).open(&block) end
register(klass, ext, prio = -1, meth = true)
click to toggle source
# File lib/lingo/database.rb, line 54 def register(klass, ext, prio = -1, meth = true) BACKENDS.insert(prio, name = klass.name[/::(\w+)Store\z/, 1]) Array(ext).each { |i| BACKEND_BY_EXT[i.insert(0, '.')] = name } klass.const_set(:EXT, ext) klass.class_eval('def store_ext; EXT; end', __FILE__, __LINE__) if meth end
Public Instance Methods
[](key)
click to toggle source
# File lib/lingo/database.rb, line 142 def [](key) val = _val(key) unless closed? val.split(FLD_SEP) if val end
[]=(key, val)
click to toggle source
# File lib/lingo/database.rb, line 147 def []=(key, val) return if closed? val = @val[key].concat(val) val.uniq! val = val.join(FLD_SEP) @crypt ? _set(*Crypter.encode(key, val)) : _set(key, val) end
close()
click to toggle source
# File lib/lingo/database.rb, line 125 def close _close unless closed? @db = nil self end
closed?()
click to toggle source
# File lib/lingo/database.rb, line 112 def closed? !@db || _closed? end
each() { |_encode!(key), _encode!(val)| ... }
click to toggle source
# File lib/lingo/database.rb, line 138 def each _each { |key, val| yield _encode!(key), _encode!(val) } unless closed? end
open() { |self| ... }
click to toggle source
# File lib/lingo/database.rb, line 116 def open @db = _open if closed? block_given? ? yield(self) : self rescue => err raise DatabaseError.new(:open, @stofile, err) ensure close if @db && block_given? end
to_h()
click to toggle source
# File lib/lingo/database.rb, line 132 def to_h hash = {} each { |key, val| hash[key.freeze] = val } hash end
warn(*msg)
click to toggle source
# File lib/lingo/database.rb, line 157 def warn(*msg) lingo.warn(*msg) end
Private Instance Methods
_clear()
click to toggle source
# File lib/lingo/database.rb, line 195 def _clear File.delete(@stofile) if File.exist?(@stofile) end
_close()
click to toggle source
# File lib/lingo/database.rb, line 203 def _close @db.close end
_closed?()
click to toggle source
# File lib/lingo/database.rb, line 207 def _closed? @db.closed? end
_each() { |key, val| ... }
click to toggle source
# File lib/lingo/database.rb, line 211 def _each @db.each { |key, val| yield key, val } end
_encode!(str)
click to toggle source
# File lib/lingo/database.rb, line 230 def _encode!(str) str.force_encoding(ENCODING) end
_get(key)
click to toggle source
# File lib/lingo/database.rb, line 219 def _get(key) @db[key] end
_open()
click to toggle source
# File lib/lingo/database.rb, line 199 def _open raise NotImplementedError end
_set(key, val)
click to toggle source
# File lib/lingo/database.rb, line 215 def _set(key, val) @db[key] = val end
_val(key)
click to toggle source
# File lib/lingo/database.rb, line 223 def _val(key) if val = _get(@crypt ? Crypter.digest(key) : key) _encode!(val) @crypt ? Crypter.decode(key, val) : val end end
config_hash()
click to toggle source
# File lib/lingo/database.rb, line 163 def config_hash hashes = [config] if use_lex = config['use-lex'] hashes.concat(lingo. dictionary_config['databases']. values_at(*use_lex.split(SEP_RE))) end Crypter.digest(hashes.inspect) end
convert(verbose = lingo.config.stderr.tty?)
click to toggle source
# File lib/lingo/database.rb, line 234 def convert(verbose = lingo.config.stderr.tty?) src = Source.from_config(config, @id) sep, hyphenate, key_map, val_map = prepare_lex Progress.new(self, src, verbose) { |progress| create { src.each { |key, val| progress << src.pos set_key(src, key, val, sep) { |keys, cnt| key = keys.map!(&key_map).join(sep) val = val.map { |v| val_map[v.split(sep)].join(sep) } if val_map hyphenate.repeated_permutation(cnt - 1) { |h| set_key(src, keys. zip(h).join, val, sep) unless h.uniq.size == 1 } if hyphenate [key, val] } } uptodate! } } end
create() { || ... }
click to toggle source
# File lib/lingo/database.rb, line 190 def create _clear open { yield } end
prepare_lex()
click to toggle source
# File lib/lingo/database.rb, line 272 def prepare_lex use_lex = config['use-lex'] or return args = [{ 'source' => use_lex.split(SEP_RE), 'mode' => config['lex-mode'] }, lingo] dic = Language::Dictionary.new(*args) gra = Language::Grammar.new(*args) args = nil wac = Language::WA_COMPOUND lac = Language::LA_COMPOUND if inflect = config['inflect'] inflect, wc = inflect == true ? %w[s e] : inflect.split(SEP_RE), 'a' if cfg = lingo.dictionary_config['inflect'] and suffixes = cfg[wc] wc, re = /#{wc}/, /\A[^#]+/ else warn "#{self.class}: No suffixes to inflect ##{wc}: #{@id}" inflect = false end end [sep = ' ', config['hyphenate'] && [sep, '-'], lambda { |form| word = dic.find_word(form) if word.unknown? comp = gra.find_compound(form) comp.attr == wac && comp.lex_form(lac) || (comp.identified? ? comp.lex_form : comp.form) else word.identified? ? word.lex_form : word.form end }, inflect && lambda { |forms| inflectables = [] forms.each { |form| word = dic.find_word(word_form = form[re]) if word.identified? && _form = word.lex_form(wc) inflectables << form if form == _form else unless inflectables.empty? word = gra.find_compound_head(word_form) || word if word.unknown? if word.attr?(*inflect) && suffix = suffixes[word.genders.compact.first] inflectables.each { |lex_form| lex_form << suffix } end end break forms end } }] end
set_key(src, key, val, sep, len = 3) { |keys, cnt| ... }
click to toggle source
# File lib/lingo/database.rb, line 258 def set_key(src, key, val, sep, len = 3) if key key.chomp!('.') if sep && key.include?(sep) keys = key.split(sep); cnt = keys.size key, val = yield keys, cnt if block_given? self[keys[0, len].join(sep)] = ["#{KEY_REF}#{cnt}"] if cnt > len end end src.set(self, key, val) end
uptodate!()
click to toggle source
# File lib/lingo/database.rb, line 186 def uptodate! @db[SYS_KEY] = @source_key.call end
uptodate?(file = @stofile)
click to toggle source
# File lib/lingo/database.rb, line 175 def uptodate?(file = @stofile) src = Pathname.new(@srcfile) @source_key = lambda { [src.size, src.mtime, VERSION, config_hash].join(FLD_SEP) } sys_key = open { @db[SYS_KEY] } if File.exist?(file) sys_key && (!src.exist? || sys_key == @source_key.call) end