llt-helpers 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +8 -0
- data/lib/llt/helpers.rb +15 -0
- data/lib/llt/helpers/configuration.rb +44 -0
- data/lib/llt/helpers/constantize.rb +25 -0
- data/lib/llt/helpers/equality.rb +28 -0
- data/lib/llt/helpers/functions.rb +26 -0
- data/lib/llt/helpers/initialize.rb +28 -0
- data/lib/llt/helpers/metrical.rb +31 -0
- data/lib/llt/helpers/normalizer.rb +28 -0
- data/lib/llt/helpers/pluralize.rb +23 -0
- data/lib/llt/helpers/positions.rb +93 -0
- data/lib/llt/helpers/primitive_cache.rb +37 -0
- data/lib/llt/helpers/query_methods.rb +30 -0
- data/lib/llt/helpers/roman_numerals.rb +50 -0
- data/lib/llt/helpers/terminology.rb +219 -0
- data/lib/llt/helpers/transformer.rb +33 -0
- data/lib/llt/helpers/version.rb +5 -0
- data/llt-helpers.gemspec +27 -0
- data/spec/lib/llt/helpers/configuration_spec.rb +77 -0
- data/spec/lib/llt/helpers/constantize_spec.rb +79 -0
- data/spec/lib/llt/helpers/equality_spec.rb +48 -0
- data/spec/lib/llt/helpers/functions_spec.rb +47 -0
- data/spec/lib/llt/helpers/initialize_spec.rb +50 -0
- data/spec/lib/llt/helpers/metrical_spec.rb +40 -0
- data/spec/lib/llt/helpers/normalizer_spec.rb +57 -0
- data/spec/lib/llt/helpers/pluralize_spec.rb +38 -0
- data/spec/lib/llt/helpers/positions_spec.rb +108 -0
- data/spec/lib/llt/helpers/primitive_cache_spec.rb +65 -0
- data/spec/lib/llt/helpers/query_methods_spec.rb +67 -0
- data/spec/lib/llt/helpers/roman_numerals_spec.rb +41 -0
- data/spec/lib/llt/helpers/terminology_spec.rb +165 -0
- data/spec/lib/llt/helpers/transformer_spec.rb +49 -0
- data/spec/spec_helper.rb +22 -0
- metadata +182 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'dalli'
|
2
|
+
|
3
|
+
module LLT
|
4
|
+
module Helpers
|
5
|
+
module PrimitiveCache
|
6
|
+
def self.included(obj)
|
7
|
+
obj.extend(ClassMethods)
|
8
|
+
end
|
9
|
+
|
10
|
+
def enable_cache
|
11
|
+
@cache_enabled = true
|
12
|
+
end
|
13
|
+
|
14
|
+
def disable_cache
|
15
|
+
@cache_enabled = false
|
16
|
+
end
|
17
|
+
|
18
|
+
def cache
|
19
|
+
self.class.cache
|
20
|
+
end
|
21
|
+
|
22
|
+
def cached(key)
|
23
|
+
if @cache_enabled
|
24
|
+
self.class.cache.fetch(key) { yield } #[key] ||= yield # with Dalli use
|
25
|
+
else
|
26
|
+
yield
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
module ClassMethods
|
31
|
+
def cache
|
32
|
+
@cache ||= Dalli::Client.new # {}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module LLT
|
2
|
+
module Helpers
|
3
|
+
module QueryMethods
|
4
|
+
def add_query_methods_for(key_term, use: nil, delegate_to: nil)
|
5
|
+
raise ArgumentError, "Can't use :use and :delegate_to together" if use && delegate_to
|
6
|
+
|
7
|
+
meths = t.values_for(key_term)
|
8
|
+
used_var = use || "@#{key_term}"
|
9
|
+
meths.each do |meth|
|
10
|
+
body = if delegate_to
|
11
|
+
"#{delegate_to}.#{meth}?"
|
12
|
+
else
|
13
|
+
"#{used_var} == :#{t.value_for(key_term, meth)}"
|
14
|
+
end
|
15
|
+
|
16
|
+
class_eval <<-STR
|
17
|
+
def #{meth}?
|
18
|
+
#{body}
|
19
|
+
end
|
20
|
+
STR
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
def t
|
26
|
+
Terminology
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'llt/constants/numerals'
|
2
|
+
|
3
|
+
module LLT
|
4
|
+
module Helpers
|
5
|
+
module RomanNumerals
|
6
|
+
|
7
|
+
# Primitive implementation to detect and convert Roman Numerals.
|
8
|
+
|
9
|
+
class << self
|
10
|
+
|
11
|
+
# Uncapitalized numerals will NOT be detected atm.
|
12
|
+
def roman?(value)
|
13
|
+
/^[CDILMVX]*$/.match(value)
|
14
|
+
end
|
15
|
+
|
16
|
+
# 4 to IV
|
17
|
+
def to_roman(value)
|
18
|
+
res = ""
|
19
|
+
numerals.each do |dec, _|
|
20
|
+
while value >= dec
|
21
|
+
value -= dec
|
22
|
+
res << numerals[dec]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
res
|
27
|
+
end
|
28
|
+
|
29
|
+
# IV to 4
|
30
|
+
def to_decimal(value)
|
31
|
+
res = 0
|
32
|
+
numerals.each do |_, rom|
|
33
|
+
while value.start_with?(rom)
|
34
|
+
value = value[rom.length..-1]
|
35
|
+
res += numerals.key(rom)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
res
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def numerals
|
45
|
+
LLT::Constants::NUMERALS
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,219 @@
|
|
1
|
+
module LLT
|
2
|
+
module Helpers
|
3
|
+
module Terminology
|
4
|
+
class << self
|
5
|
+
def term_for(key)
|
6
|
+
FULL_TABLE[key.to_sym]
|
7
|
+
end
|
8
|
+
|
9
|
+
# rename, scrap term
|
10
|
+
def key_term_for(key)
|
11
|
+
KEY_TABLE[key.to_sym]
|
12
|
+
end
|
13
|
+
|
14
|
+
def value_term_for(key, value)
|
15
|
+
t = VALUE_TABLE[key]
|
16
|
+
if t.nil?
|
17
|
+
# tries to normalize the key
|
18
|
+
k = key_term_for(key)
|
19
|
+
|
20
|
+
# hacky solution to normalize inflection class integers
|
21
|
+
return value.to_i if inflection_class_number_as_string?(key, value)
|
22
|
+
|
23
|
+
t = VALUE_TABLE[k]
|
24
|
+
return value unless t
|
25
|
+
end
|
26
|
+
t[val_to_sym_or_integer(value)] || value
|
27
|
+
end
|
28
|
+
alias :value_for :value_term_for
|
29
|
+
|
30
|
+
def inflection_class_number_as_string?(key, value)
|
31
|
+
key == inflection_class && value.kind_of?(String) && value.match(/^\d*$/)
|
32
|
+
end
|
33
|
+
|
34
|
+
def val_to_sym_or_integer(val)
|
35
|
+
# Normalizes strings to symbols or integers, but leaves fixnums intact
|
36
|
+
case val
|
37
|
+
when /^\d*$/ then val.to_i
|
38
|
+
when String then val.to_sym
|
39
|
+
else val
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def values_for(key_term, exclude: nil)
|
44
|
+
v = VALUE_TABLE[key_term_for(key_term)]
|
45
|
+
v ? v.keys : []
|
46
|
+
end
|
47
|
+
|
48
|
+
def norm_values_for(key_term, format: DEFAULT_FORMAT[key_term])
|
49
|
+
NORM_VALUES[key_term].map { |values| send(values.first, format) }
|
50
|
+
end
|
51
|
+
|
52
|
+
def method_missing(meth, *args, &blk)
|
53
|
+
meth
|
54
|
+
end
|
55
|
+
|
56
|
+
# implement to_ary everytime you do crazy method_missing stuff.
|
57
|
+
# #flatten will bite you otherwise!
|
58
|
+
def to_ary
|
59
|
+
nil
|
60
|
+
end
|
61
|
+
|
62
|
+
# Keywords
|
63
|
+
|
64
|
+
def inflection_class
|
65
|
+
:inflection_class
|
66
|
+
end
|
67
|
+
|
68
|
+
def tempus
|
69
|
+
:tempus
|
70
|
+
end
|
71
|
+
|
72
|
+
def casus
|
73
|
+
:casus
|
74
|
+
end
|
75
|
+
|
76
|
+
def type
|
77
|
+
:type
|
78
|
+
end
|
79
|
+
|
80
|
+
def numerus
|
81
|
+
:numerus
|
82
|
+
end
|
83
|
+
|
84
|
+
def sexus
|
85
|
+
:sexus
|
86
|
+
end
|
87
|
+
|
88
|
+
def noe
|
89
|
+
:number_of_endings
|
90
|
+
end
|
91
|
+
|
92
|
+
def modus
|
93
|
+
:modus
|
94
|
+
end
|
95
|
+
|
96
|
+
def genus
|
97
|
+
:genus
|
98
|
+
end
|
99
|
+
|
100
|
+
def persona
|
101
|
+
:persona
|
102
|
+
end
|
103
|
+
|
104
|
+
def deponens
|
105
|
+
:deponens
|
106
|
+
end
|
107
|
+
|
108
|
+
DEFAULT_FORMAT = { casus: :numeric,
|
109
|
+
numerus: :numeric,
|
110
|
+
tempus: :abbr,
|
111
|
+
sexus: :abbr,
|
112
|
+
modus: :abbr,
|
113
|
+
type: :full,
|
114
|
+
genus: :abbr,
|
115
|
+
persona: :numeric }
|
116
|
+
|
117
|
+
# Convenience Methods
|
118
|
+
|
119
|
+
def self.create_three_way_getter_methods(abbr, full, i, type)
|
120
|
+
class_eval <<-STR
|
121
|
+
def #{full}(arg = :#{DEFAULT_FORMAT[type]})
|
122
|
+
case arg
|
123
|
+
when :numeric then #{i + 1}
|
124
|
+
when :abbr then :#{abbr}
|
125
|
+
when :full then :#{full}
|
126
|
+
when :camelcase then :#{camelcased(full)}
|
127
|
+
end
|
128
|
+
end
|
129
|
+
alias :#{abbr} :#{full}
|
130
|
+
STR
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.camelcased(str)
|
134
|
+
str.to_s.split("_").map(&:capitalize).join
|
135
|
+
end
|
136
|
+
|
137
|
+
NORM_VALUES = { casus: [[:nom, :nominativus], [:gen, :genetivus], [:dat, :dativus], [:acc, :accusativus], [:voc, :vocativus], [:abl, :ablativus]],
|
138
|
+
numerus: [[:sg, :singularis], [:pl, :pluralis]],
|
139
|
+
tempus: [[:pr, :praesens], [:impf, :imperfectum], [:fut, :futurum], [:pf, :perfectum], [:pqpf, :plusquamperfectum], [:fut_ex, :futurum_exactum]],
|
140
|
+
sexus: [[:m, :masculinum], [:f, :femininum], [:n, :neutrum]],
|
141
|
+
modus: [[:ind, :indicativus], [:con, :coniunctivus], [:imp, :imperativum], [:part, :participium], [:inf, :infinitivum], [:gerundium, :gerundium], [:gerundivum, :gerundivum]],
|
142
|
+
type: [[:noun, :noun], [:adj, :adjective], [:verb, :verb]],#, [:gerundive, :gerundive], [:gerund, :gerund]],
|
143
|
+
genus: [[:act, :activum], [:pass, :passivum]],
|
144
|
+
persona: [[:first, :first], [:second, :second], [:third, :third]]
|
145
|
+
}
|
146
|
+
|
147
|
+
NORM_VALUES.each do |type, getters|
|
148
|
+
getters.each_with_index do |(abbr, full), i|
|
149
|
+
create_three_way_getter_methods(abbr, full, i, type)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
kt = { inflection_class => %i{ inflection_class inflectable_class iclass itype },
|
155
|
+
tempus => %i{ tempus tense },
|
156
|
+
casus => %i{ casus case },
|
157
|
+
numerus => %i{ numerus },
|
158
|
+
modus => %i{ mood modus },
|
159
|
+
sexus => %i{ sexus gender },
|
160
|
+
genus => %i{ genus diathesis voice },
|
161
|
+
type => %i{ type pos },
|
162
|
+
noe => %i{ number_of_endings noe },
|
163
|
+
nom(:abbr) => %i{ nominative nom },
|
164
|
+
deponens => %i{ dep deponens },
|
165
|
+
}
|
166
|
+
|
167
|
+
KEY_TABLE = kt.each_with_object({}) do |(norm_term, terms), h|
|
168
|
+
terms.each { |term| h[term] = norm_term }
|
169
|
+
end
|
170
|
+
|
171
|
+
|
172
|
+
vt = {
|
173
|
+
tempus => { pr => %i{ present praesens pr },
|
174
|
+
pf => %i{ perfect perfectum pf },
|
175
|
+
fut => %i{ future futurum fut },
|
176
|
+
pqpf => %i{ pluperfect plusquamperfectum pqpf },
|
177
|
+
fut_ex => %i{ future_perfect futurum_exactum fut_ex },
|
178
|
+
impf => %i{ imperfect imperfectum impf }, },
|
179
|
+
casus => { nom => %i{ nom nominative nominativus } + [1],
|
180
|
+
gen => %i{ gen genetive genetivus } + [2],
|
181
|
+
dat => %i{ dat dative dativus } + [3],
|
182
|
+
acc => %i{ acc accusative accusativus } + [4],
|
183
|
+
voc => %i{ voc vocative vocativus } + [5],
|
184
|
+
abl => %i{ abl ablative ablativus } + [6], },
|
185
|
+
numerus => { sg => %i{ singularis singular } + [1],
|
186
|
+
pl => %i{ pluralis plural } + [2], },
|
187
|
+
genus => { activum => %i{ activum act },
|
188
|
+
passivum => %i{ passivum pass }, },
|
189
|
+
modus => { indicativus => %i{ indicativus ind indicative },
|
190
|
+
coniunctivus => %i{ coniunctivus con conjunctive subjunctive },
|
191
|
+
imperativus => %i{ imperativus imp imperativum },
|
192
|
+
participium => %i{ participium part participle },
|
193
|
+
gerundium => %i{ gerundium gerund },
|
194
|
+
gerundivum => %i{ gerundivum gerundive },
|
195
|
+
infinitivum => %i{ infinitivum inf infinitive },
|
196
|
+
supinum => %i{ supinum sup }, },
|
197
|
+
sexus => { m => %i{ m masc masculine masculinum },
|
198
|
+
f => %i{ f fem feminine femininum },
|
199
|
+
n => %i{ n neut neuter neutrum }, },
|
200
|
+
type => { noun => %i{ noun substantive },
|
201
|
+
adj => %i{ adj adjective },
|
202
|
+
verb => %i{ verb }, },
|
203
|
+
# ...
|
204
|
+
noe => { 1 => %i{ one_ending },
|
205
|
+
2 => %i{ two_endings },
|
206
|
+
3 => %i{ three_endings }, }
|
207
|
+
}
|
208
|
+
|
209
|
+
VALUE_TABLE = vt.each_with_object({}) do |(key_term, hash), h|
|
210
|
+
nh = hash.each_with_object({}) do |(norm_term, values), nested_h|
|
211
|
+
values.each { |val| nested_h[val] = norm_term }
|
212
|
+
end
|
213
|
+
h[key_term] = nh
|
214
|
+
end
|
215
|
+
|
216
|
+
FULL_TABLE = KEY_TABLE.merge(VALUE_TABLE.values.inject({}) { |new, old| new.merge(old) })
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module LLT
|
2
|
+
module Helpers
|
3
|
+
module Transformer
|
4
|
+
def to_hash(custom: {}, whitelist: [], blacklist: [], root: false, keys: :to_sym)
|
5
|
+
overwritten = custom.keys.map(&:to_sym)
|
6
|
+
res = instance_variables.each_with_object({}) do |var, hash|
|
7
|
+
sym = inst_to_sym(var)
|
8
|
+
|
9
|
+
next if whitelist.any? && ! whitelist.include?(sym)
|
10
|
+
next if blacklist.include?(sym)
|
11
|
+
next if overwritten.include?(sym)
|
12
|
+
|
13
|
+
hash[sym.send(keys)] = instance_variable_get(var)
|
14
|
+
end
|
15
|
+
|
16
|
+
res.merge!(custom)
|
17
|
+
|
18
|
+
if root
|
19
|
+
root = self.class.name if root == true
|
20
|
+
{ root => res }
|
21
|
+
else
|
22
|
+
res
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def inst_to_sym(inst_var)
|
29
|
+
inst_var.to_s.delete("@").to_sym
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/llt-helpers.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'llt/helpers/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "llt-helpers"
|
8
|
+
spec.version = LLT::Helpers::VERSION
|
9
|
+
spec.authors = ["LFDM", "lichtr"]
|
10
|
+
spec.email = ["1986gh@gmail.com", "robert.lichtensteiner@gmail.com"]
|
11
|
+
spec.description = %q{LLT Helpers}
|
12
|
+
spec.summary = %q{Helper modules used by several llt gems}
|
13
|
+
spec.homepage = "http://christof.github.io/llt"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
spec.add_development_dependency "simplecov", "~> 0.7"
|
25
|
+
spec.add_dependency "dalli"
|
26
|
+
spec.add_dependency "llt-constants"
|
27
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe LLT::Helpers::Configuration do
|
4
|
+
class Dummy
|
5
|
+
attr_reader :something
|
6
|
+
include LLT::Helpers::Configuration
|
7
|
+
end
|
8
|
+
|
9
|
+
context "comes with an additional class method" do
|
10
|
+
describe ".configuration" do
|
11
|
+
it "provides a configuration hash" do
|
12
|
+
Dummy.configuration.should be_a Hash
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe ".uses_**" do
|
17
|
+
it "is a method missing implementation" do
|
18
|
+
expect { Dummy.uses_something { "test" } }.not_to raise_error
|
19
|
+
end
|
20
|
+
|
21
|
+
it "fills the classes configuration hash will procs" do
|
22
|
+
pending
|
23
|
+
Dummy.uses_something { "test" }
|
24
|
+
conf = Dummy.configuration[:something]
|
25
|
+
conf.should == "test"
|
26
|
+
end
|
27
|
+
|
28
|
+
it "reloads the configuration which might have changed in the meantime" do
|
29
|
+
Dummy.uses_something { "test" }
|
30
|
+
d1 = Dummy.new
|
31
|
+
d1.configure
|
32
|
+
Dummy.uses_something { "no_test" }
|
33
|
+
d2 = Dummy.new
|
34
|
+
d2.configure
|
35
|
+
|
36
|
+
d1.something.should == "test"
|
37
|
+
d2.something.should == "no_test"
|
38
|
+
end
|
39
|
+
|
40
|
+
it "stores the return value of the blk to avoid needless throw-away service objects" do
|
41
|
+
Dummy.uses_something { "test" }
|
42
|
+
d1 = Dummy.new
|
43
|
+
d2 = Dummy.new
|
44
|
+
d1.something.should be d2.something
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
let(:dummy) { Dummy.new }
|
50
|
+
|
51
|
+
describe "#configure" do
|
52
|
+
it "sets instance variables defined in the configuration hash" do
|
53
|
+
Dummy.uses_something { "anything" }
|
54
|
+
dummy.configure
|
55
|
+
dummy.instance_variable_get("@something").should == "anything"
|
56
|
+
end
|
57
|
+
|
58
|
+
it "takes an options hash to overwrite the default configuration" do
|
59
|
+
Dummy.uses_something { "anything" }
|
60
|
+
dummy.configure(something: "nothing")
|
61
|
+
dummy.instance_variable_get("@something").should == "nothing"
|
62
|
+
end
|
63
|
+
|
64
|
+
it "initializes only preconfiguraed variables and does nothing with other options" do
|
65
|
+
Dummy.uses_something { "anything" }
|
66
|
+
dummy.configure(another_thing: "thing")
|
67
|
+
dummy.instance_variable_get("@something").should == "anything"
|
68
|
+
dummy.instance_variable_get("@another_thing").should be_nil
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "#configuration" do
|
73
|
+
it "returns the classes configuration" do
|
74
|
+
dummy.configuration.should_not be_nil
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|