llt-helpers 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +6 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +29 -0
  6. data/Rakefile +8 -0
  7. data/lib/llt/helpers.rb +15 -0
  8. data/lib/llt/helpers/configuration.rb +44 -0
  9. data/lib/llt/helpers/constantize.rb +25 -0
  10. data/lib/llt/helpers/equality.rb +28 -0
  11. data/lib/llt/helpers/functions.rb +26 -0
  12. data/lib/llt/helpers/initialize.rb +28 -0
  13. data/lib/llt/helpers/metrical.rb +31 -0
  14. data/lib/llt/helpers/normalizer.rb +28 -0
  15. data/lib/llt/helpers/pluralize.rb +23 -0
  16. data/lib/llt/helpers/positions.rb +93 -0
  17. data/lib/llt/helpers/primitive_cache.rb +37 -0
  18. data/lib/llt/helpers/query_methods.rb +30 -0
  19. data/lib/llt/helpers/roman_numerals.rb +50 -0
  20. data/lib/llt/helpers/terminology.rb +219 -0
  21. data/lib/llt/helpers/transformer.rb +33 -0
  22. data/lib/llt/helpers/version.rb +5 -0
  23. data/llt-helpers.gemspec +27 -0
  24. data/spec/lib/llt/helpers/configuration_spec.rb +77 -0
  25. data/spec/lib/llt/helpers/constantize_spec.rb +79 -0
  26. data/spec/lib/llt/helpers/equality_spec.rb +48 -0
  27. data/spec/lib/llt/helpers/functions_spec.rb +47 -0
  28. data/spec/lib/llt/helpers/initialize_spec.rb +50 -0
  29. data/spec/lib/llt/helpers/metrical_spec.rb +40 -0
  30. data/spec/lib/llt/helpers/normalizer_spec.rb +57 -0
  31. data/spec/lib/llt/helpers/pluralize_spec.rb +38 -0
  32. data/spec/lib/llt/helpers/positions_spec.rb +108 -0
  33. data/spec/lib/llt/helpers/primitive_cache_spec.rb +65 -0
  34. data/spec/lib/llt/helpers/query_methods_spec.rb +67 -0
  35. data/spec/lib/llt/helpers/roman_numerals_spec.rb +41 -0
  36. data/spec/lib/llt/helpers/terminology_spec.rb +165 -0
  37. data/spec/lib/llt/helpers/transformer_spec.rb +49 -0
  38. data/spec/spec_helper.rb +22 -0
  39. 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
@@ -0,0 +1,5 @@
1
+ module LLT
2
+ module Helpers
3
+ VERSION = "0.0.4"
4
+ end
5
+ end
@@ -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