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.
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