tunable 0.0.1
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 +1 -0
- data/Gemfile +4 -0
- data/README.md +115 -0
- data/Rakefile +8 -0
- data/generators/tunable_migration/templates/migration.rb +23 -0
- data/generators/tunable_migration/tunable_migration_generator.rb +7 -0
- data/lib/tunable/core_ext.rb +41 -0
- data/lib/tunable/emoji_fix.rb +5 -0
- data/lib/tunable/hasher.rb +30 -0
- data/lib/tunable/model.rb +260 -0
- data/lib/tunable/normalizer.rb +34 -0
- data/lib/tunable/setting.rb +59 -0
- data/lib/tunable/version.rb +5 -0
- data/lib/tunable.rb +6 -0
- data/spec/schema.rb +17 -0
- data/spec/spec_helper.rb +40 -0
- data/spec/tunable/defaults_spec.rb +143 -0
- data/spec/tunable/normalization_spec.rb +344 -0
- data/spec/tunable/querying_spec.rb +259 -0
- data/spec/tunable/setters_spec.rb +63 -0
- data/tunable.gemspec +27 -0
- metadata +153 -0
@@ -0,0 +1,143 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
|
4
|
+
describe 'defaults' do
|
5
|
+
|
6
|
+
TEST_SETTINGS = {
|
7
|
+
:true_setting => { :default => true, :strict => true },
|
8
|
+
:false_setting => { :default => false, :strict => true },
|
9
|
+
:numeric_setting => { :default => 10, :strict => true },
|
10
|
+
:string_setting => { :default => 'hola', :strict => true }
|
11
|
+
}
|
12
|
+
|
13
|
+
describe 'without defaults' do
|
14
|
+
|
15
|
+
before do
|
16
|
+
TunableModel.main_settings(*TEST_SETTINGS.keys)
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'getting' do
|
20
|
+
|
21
|
+
describe 'and value is not set' do
|
22
|
+
|
23
|
+
before do
|
24
|
+
@foo = TunableModel.new
|
25
|
+
end
|
26
|
+
|
27
|
+
describe 'settings_hash' do
|
28
|
+
TEST_SETTINGS.each do |key, opts|
|
29
|
+
it "#{key} is not present" do
|
30
|
+
@foo.settings_hash[key].should be_nil
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'get_setting' do
|
36
|
+
TEST_SETTINGS.each do |key, opts|
|
37
|
+
it "#{key} is not present" do
|
38
|
+
@foo.get_main_setting(key).should be_nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
describe 'with defaults' do
|
50
|
+
|
51
|
+
before do
|
52
|
+
TunableModel.main_settings(TEST_SETTINGS)
|
53
|
+
end
|
54
|
+
|
55
|
+
describe 'getting' do
|
56
|
+
|
57
|
+
describe 'and value is not set' do
|
58
|
+
|
59
|
+
before do
|
60
|
+
@foo = TunableModel.new
|
61
|
+
end
|
62
|
+
|
63
|
+
describe 'settings_hash' do
|
64
|
+
|
65
|
+
TEST_SETTINGS.each do |key, opts|
|
66
|
+
it "#{key} is not present" do
|
67
|
+
@foo.settings_hash[key].should be_nil
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
describe 'get_setting' do
|
74
|
+
|
75
|
+
TEST_SETTINGS.each do |key, opts|
|
76
|
+
it "#{key} is not present" do
|
77
|
+
@foo.get_main_setting(key).should == opts[:default]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
describe 'and value is set' do
|
86
|
+
|
87
|
+
before do
|
88
|
+
@new_settings = {
|
89
|
+
:true_setting => false,
|
90
|
+
:false_setting => true,
|
91
|
+
:numeric_setting => 5,
|
92
|
+
:string_setting => 'chao'
|
93
|
+
}
|
94
|
+
|
95
|
+
@foo = TunableModel.new
|
96
|
+
@foo.update_attributes(@new_settings)
|
97
|
+
end
|
98
|
+
|
99
|
+
describe 'settings_hash' do
|
100
|
+
|
101
|
+
TEST_SETTINGS.each do |key, val|
|
102
|
+
it "#{key} equals new val" do
|
103
|
+
@foo.main_settings[key].should == @new_settings[key]
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
describe 'get_setting' do
|
110
|
+
|
111
|
+
TEST_SETTINGS.each do |key, val|
|
112
|
+
it "#{key} equals new val" do
|
113
|
+
@foo.get_main_setting(key).should == @new_settings[key]
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
describe 'settings with proc as default value' do
|
125
|
+
|
126
|
+
before do
|
127
|
+
TunableModel.main_settings true_setting: {
|
128
|
+
:default => lambda{ |o| o.name == "a" }
|
129
|
+
}
|
130
|
+
end
|
131
|
+
|
132
|
+
it "setting will respond to lambda condition" do
|
133
|
+
model = TunableModel.create(name: "a")
|
134
|
+
expect(model.true_setting).to be(true)
|
135
|
+
end
|
136
|
+
|
137
|
+
it "setting will respond to lambda condition" do
|
138
|
+
model = TunableModel.create(name: "b")
|
139
|
+
expect(model.true_setting).to be(false)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
@@ -0,0 +1,344 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe 'normalization' do
|
4
|
+
|
5
|
+
before :all do
|
6
|
+
load_main_settings!
|
7
|
+
@model = TunableModel.create(name: "Yay, I'm settable!")
|
8
|
+
end
|
9
|
+
|
10
|
+
VALUE_TYPES = {
|
11
|
+
:main => {
|
12
|
+
:truthy => 'true',
|
13
|
+
:falsy => 'false',
|
14
|
+
:t => 't',
|
15
|
+
:f => 'f',
|
16
|
+
:foo => 'foo'
|
17
|
+
},
|
18
|
+
:numbers => {
|
19
|
+
:number_0 => '0',
|
20
|
+
:number_1 => '1',
|
21
|
+
:number_of_the_beast => '666'
|
22
|
+
},
|
23
|
+
:onoffs => {
|
24
|
+
:on => 'on',
|
25
|
+
:off => 'off'
|
26
|
+
},
|
27
|
+
:yesnoes => {
|
28
|
+
:yes => 'yes',
|
29
|
+
:no => 'no',
|
30
|
+
:y => 'y',
|
31
|
+
:n => 'n',
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
describe 'before saving to DB' do
|
36
|
+
|
37
|
+
after do
|
38
|
+
@model.boolean_setting = nil
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'the getter returns true for 1' do
|
42
|
+
@model.boolean_setting = 1
|
43
|
+
@model.boolean_setting.should === true
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'the getter returns false for 0' do
|
47
|
+
@model.boolean_setting = '0' # as string
|
48
|
+
@model.boolean_setting.should === false
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
describe 'when inserting to DB' do
|
54
|
+
|
55
|
+
def get_value(context, key)
|
56
|
+
id = @model.id
|
57
|
+
sql = "select `value` from `settings` where `settable_id` = #{id} and `context` = '#{context}' and `key` = '#{key}';"
|
58
|
+
res = ActiveRecord::Base.connection.execute(sql)
|
59
|
+
# puts res.inspect
|
60
|
+
res[0]['value']
|
61
|
+
end
|
62
|
+
|
63
|
+
describe 'creating a new setting directly' do
|
64
|
+
|
65
|
+
before :all do
|
66
|
+
@settings = []
|
67
|
+
|
68
|
+
VALUE_TYPES.each do |context, values|
|
69
|
+
values.each do |key, val|
|
70
|
+
# puts "#{context} -> #{key} -> #{val}"
|
71
|
+
setting = Tunable::Setting.create(:context => context, :key => key, :value => val, :settable_id => @model.id)
|
72
|
+
@settings << setting
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
after :all do
|
78
|
+
Tunable::Setting.delete_all
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'keeps 1 as 1' do
|
82
|
+
get_value(:numbers, :number_1).should == '1'
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'keeps 0 as 0' do
|
86
|
+
get_value(:numbers, :number_0).should == '0'
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'keeps 666 as 666' do
|
90
|
+
get_value(:numbers, :number_of_the_beast).should == '666'
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'keeps foo as foo' do
|
94
|
+
get_value(:main, :foo).should == 'foo'
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'normalizes booleany true values to 1' do
|
98
|
+
get_value(:main, :truthy).should == '1'
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'normalizes booleany false values to 0' do
|
102
|
+
get_value(:main, :falsy).should == '0'
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'normalizes t (from true) to 1' do
|
106
|
+
get_value(:main, :t).should == '1'
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'normalizes f (from false) to 0' do
|
110
|
+
get_value(:main, :f).should == '0'
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'normalizes on to 1' do
|
114
|
+
get_value(:onoffs, :on).should == '1'
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'normalizes off to 0' do
|
118
|
+
get_value(:onoffs, :off).should == '0'
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'normalizes y to 1' do
|
122
|
+
get_value(:yesnoes, :y).should == '1'
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'normalizes n to 0' do
|
126
|
+
get_value(:yesnoes, :n).should == '0'
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'normalizes yes to 1' do
|
130
|
+
get_value(:yesnoes, :yes).should == '1'
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'normalizes no to 0' do
|
134
|
+
get_value(:yesnoes, :no).should == '0'
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
describe 'using main settings' do
|
140
|
+
|
141
|
+
it 'keeps 1 as 1' do
|
142
|
+
@model.update_attribute(:number_setting, 1)
|
143
|
+
get_value(:main, :number_setting).should == '1'
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'keeps 0 as 0' do
|
147
|
+
@model.update_attribute(:number_setting, '0')
|
148
|
+
get_value(:main, :number_setting).should == '0'
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'keeps foo as foo' do
|
152
|
+
@model.update_attribute(:other_setting, 'foo')
|
153
|
+
get_value(:main, :other_setting).should == 'foo'
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'normalizes booleany true values to 1' do
|
157
|
+
@model.update_attribute(:boolean_setting, true)
|
158
|
+
get_value(:main, :boolean_setting).should == '1'
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'normalizes booleany false values to 0' do
|
162
|
+
@model.update_attribute(:boolean_setting, false)
|
163
|
+
get_value(:main, :boolean_setting).should == '0'
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'normalizes on to 1' do
|
167
|
+
@model.update_attribute(:on_off_setting, 'on')
|
168
|
+
get_value(:main, :on_off_setting).should == '1'
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'normalizes off to 0' do
|
172
|
+
@model.update_attribute(:on_off_setting, 'off')
|
173
|
+
get_value(:main, :on_off_setting).should == '0'
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'normalizes on to 1' do
|
177
|
+
@model.update_attribute(:y_n_setting, 'y')
|
178
|
+
get_value(:main, :y_n_setting).should == '1'
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'normalizes off to 0' do
|
182
|
+
@model.update_attribute(:y_n_setting, 'n')
|
183
|
+
get_value(:main, :y_n_setting).should == '0'
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
|
188
|
+
describe 'using settings relationship' do
|
189
|
+
|
190
|
+
before :all do
|
191
|
+
|
192
|
+
@model.update_attributes({
|
193
|
+
:settings => VALUE_TYPES
|
194
|
+
})
|
195
|
+
end
|
196
|
+
|
197
|
+
after :all do
|
198
|
+
Tunable::Setting.delete_all
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'keeps 1 as 1' do
|
202
|
+
get_value(:numbers, :number_1).should == '1'
|
203
|
+
end
|
204
|
+
|
205
|
+
it 'keeps 0 as 0' do
|
206
|
+
get_value(:numbers, :number_0).should == '0'
|
207
|
+
end
|
208
|
+
|
209
|
+
it 'keeps 666 as 666' do
|
210
|
+
get_value(:numbers, :number_of_the_beast).should == '666'
|
211
|
+
end
|
212
|
+
|
213
|
+
it 'keeps foo as foo' do
|
214
|
+
get_value(:main, :foo).should == 'foo'
|
215
|
+
end
|
216
|
+
|
217
|
+
it 'normalizes booleany true values to 1' do
|
218
|
+
get_value(:main, :truthy).should == '1'
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'normalizes booleany false values to 0' do
|
222
|
+
get_value(:main, :falsy).should == '0'
|
223
|
+
end
|
224
|
+
|
225
|
+
it 'normalizes t (from true) to 1' do
|
226
|
+
get_value(:main, :t).should == '1'
|
227
|
+
end
|
228
|
+
|
229
|
+
it 'normalizes f (from false) to 0' do
|
230
|
+
get_value(:main, :f).should == '0'
|
231
|
+
end
|
232
|
+
|
233
|
+
it 'normalizes on to 1' do
|
234
|
+
get_value(:onoffs, :on).should == '1'
|
235
|
+
end
|
236
|
+
|
237
|
+
it 'normalizes off to 0' do
|
238
|
+
get_value(:onoffs, :off).should == '0'
|
239
|
+
end
|
240
|
+
|
241
|
+
it 'normalizes y to 1' do
|
242
|
+
get_value(:yesnoes, :y).should == '1'
|
243
|
+
end
|
244
|
+
|
245
|
+
it 'normalizes n to 0' do
|
246
|
+
get_value(:yesnoes, :n).should == '0'
|
247
|
+
end
|
248
|
+
|
249
|
+
it 'normalizes yes to 1' do
|
250
|
+
get_value(:yesnoes, :yes).should == '1'
|
251
|
+
end
|
252
|
+
|
253
|
+
it 'normalizes no to 0' do
|
254
|
+
get_value(:yesnoes, :no).should == '0'
|
255
|
+
end
|
256
|
+
|
257
|
+
end
|
258
|
+
|
259
|
+
end
|
260
|
+
|
261
|
+
# store values under raw_#{context} just to make sure we're not getting
|
262
|
+
# anything from the previous tests
|
263
|
+
describe 'getting from db' do
|
264
|
+
|
265
|
+
def insert_into_db(id, context, key, val)
|
266
|
+
keys = %w(settable_type settable_id context key value)
|
267
|
+
values = "'" + ['TunableModel', id, "raw_#{context}", key, val].join("','") + "'"
|
268
|
+
sql = "REPLACE INTO `settings` (#{keys.join(', ')}) VALUES (#{values});"
|
269
|
+
ActiveRecord::Base.connection.execute(sql)
|
270
|
+
end
|
271
|
+
|
272
|
+
before do
|
273
|
+
VALUE_TYPES.each do |context, values|
|
274
|
+
values.each do |key, val|
|
275
|
+
insert_into_db(@model.id, context, key, val)
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
def get_value_from_model(context, key)
|
281
|
+
settings = @model.reload.settings_hash
|
282
|
+
ctx = "raw_#{context}".to_sym
|
283
|
+
settings[ctx][key]
|
284
|
+
end
|
285
|
+
|
286
|
+
it 'normalizes 1 to true' do
|
287
|
+
get_value_from_model(:numbers, :number_1).should === true
|
288
|
+
end
|
289
|
+
|
290
|
+
it 'normalizes 0 to false' do
|
291
|
+
get_value_from_model(:numbers, :number_0).should === false
|
292
|
+
end
|
293
|
+
|
294
|
+
it 'keeps 666 as 666' do
|
295
|
+
get_value_from_model(:numbers, :number_of_the_beast).should == '666'
|
296
|
+
end
|
297
|
+
|
298
|
+
it 'keeps foo as foo' do
|
299
|
+
get_value_from_model(:main, :foo).should == 'foo'
|
300
|
+
end
|
301
|
+
|
302
|
+
it 'normalizes booleany true values to true' do
|
303
|
+
get_value_from_model(:main, :truthy).should === true
|
304
|
+
end
|
305
|
+
|
306
|
+
it 'normalizes booleany false values to false' do
|
307
|
+
get_value_from_model(:main, :falsy).should === false
|
308
|
+
end
|
309
|
+
|
310
|
+
it 'normalizes t (from true) to true' do
|
311
|
+
get_value_from_model(:main, :t).should === true
|
312
|
+
end
|
313
|
+
|
314
|
+
it 'normalizes f (from false) to false' do
|
315
|
+
get_value_from_model(:main, :f).should === false
|
316
|
+
end
|
317
|
+
|
318
|
+
it 'normalizes on to true' do
|
319
|
+
get_value_from_model(:onoffs, :on).should === true
|
320
|
+
end
|
321
|
+
|
322
|
+
it 'normalizes off to false' do
|
323
|
+
get_value_from_model(:onoffs, :off).should === false
|
324
|
+
end
|
325
|
+
|
326
|
+
it 'normalizes y to true' do
|
327
|
+
get_value_from_model(:yesnoes, :y).should === true
|
328
|
+
end
|
329
|
+
|
330
|
+
it 'normalizes n to false' do
|
331
|
+
get_value_from_model(:yesnoes, :n).should === false
|
332
|
+
end
|
333
|
+
|
334
|
+
it 'normalizes yes to true' do
|
335
|
+
get_value_from_model(:yesnoes, :yes).should === true
|
336
|
+
end
|
337
|
+
|
338
|
+
it 'normalizes no to false' do
|
339
|
+
get_value_from_model(:yesnoes, :no).should === false
|
340
|
+
end
|
341
|
+
|
342
|
+
end
|
343
|
+
|
344
|
+
end
|