llt-helpers 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|