simplificator-has_setting 0.3.9 → 0.4.0
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.
- data/README +104 -0
- data/Rakefile +52 -0
- data/VERSION.yml +2 -2
- data/lib/has_setting.rb +2 -0
- data/lib/has_setting/formatters.rb +17 -1
- data/test/unit/formatters_test.rb +26 -2
- metadata +16 -13
data/README
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
==What is it?
|
2
|
+
has_setting is a simple extension that enables ActiveRecord models to
|
3
|
+
store settings in a separate settings table as key/value pairs where the key and value are stored as Strings.
|
4
|
+
|
5
|
+
==History
|
6
|
+
* 0.3.10:
|
7
|
+
* added boolean and booleans formatters
|
8
|
+
* 0.3.9:
|
9
|
+
* added type :strings, :floats, :ints. They store the contents of an array as a comma separated string.
|
10
|
+
* 0.3.8:
|
11
|
+
* added dependent destroy option. no more zombie settings lingering around.
|
12
|
+
* 0.3.7:
|
13
|
+
* Gem is now built using jeweler... after messing around and bumping versions and getting
|
14
|
+
strange errors, this is 'it works' feeling coming back
|
15
|
+
* 0.3.4:
|
16
|
+
* Added custom formatter support. no new formatters though...
|
17
|
+
* 0.3.1:
|
18
|
+
* Bug Fixed: has_many(:settings) is not added to ActiveRecord::Base but only to the classes with has_setting
|
19
|
+
* Bug Fixed: options are not shared between classes
|
20
|
+
* Again changed the way settings are saved. Save is now done on parent.save with an after_save callback. (like this the settings are treated as if they were attributes of the owner)
|
21
|
+
* 0.2.x:
|
22
|
+
* Added :default option
|
23
|
+
* changed way settings are saved so that unsaved parents can have settings too
|
24
|
+
* changed nameing scheme of setting names (incompatible with versions prior 0.2.x but since nobody uses the gem i dont care :-))
|
25
|
+
* 0.1.x: First Version
|
26
|
+
|
27
|
+
|
28
|
+
==Installation
|
29
|
+
sudo gem install simplificator-has_setting
|
30
|
+
|
31
|
+
==Setup
|
32
|
+
* Add a migration that looks more or less like the one in <em>help/001_create_settings.rb</em>
|
33
|
+
* Make sure the gem is loaded when your application starts
|
34
|
+
|
35
|
+
==Config
|
36
|
+
The model you want to hold settings (i.e. User, Profile, ...):
|
37
|
+
<tt>has_setting(:name_of_the_setting)</tt>
|
38
|
+
This will create the following methods for you on the owner class:
|
39
|
+
* <tt>name_of_the_setting=(value)</tt> a standard setter
|
40
|
+
* <tt>name_of_the_setting()</tt> a standard getter (the getter method takes an optional hash to override some options, possible values are the same as the options in has_setting())
|
41
|
+
|
42
|
+
<tt>has_setting(name, options)</tt> takes an optional hash of options. Following options are supported:
|
43
|
+
<em>:type</em> allows you to convert the value:
|
44
|
+
* <em>:string</em> (default) Uses the StringFormatter to convert from/to String (actually this formatter just leaves the value as it is)
|
45
|
+
* <em>:int</em> Uses the IntFormatter to convert from/to int values.
|
46
|
+
* <em>:boolean</em> Uses the BooleanFormatter to convert from/to boolean values.
|
47
|
+
* <em>:float</em> Uses the FloatFormatter to convert from/to float values.
|
48
|
+
* <em>:ints</em> Uses the IntsFormatter to convert from/to int[]
|
49
|
+
* <em>:floats</em> Uses the FloatsFormatter to convert from/to float[]
|
50
|
+
* <em>:strings</em> Uses the StringsFormatter to convert from/to string[]
|
51
|
+
* <em>:booleans</em> Uses the BooleansFormatter to convert from/to boolean[]
|
52
|
+
<em>:default</em> allows you to specify a default value that will be returned if the setting does not exist (i.e. has never been written). Note that the default value is _ignored_ if the setting exists, no matter what the value of the setting is. The default value is returned as is, no type conversion takes place.
|
53
|
+
|
54
|
+
|
55
|
+
|
56
|
+
==How it works
|
57
|
+
A polymorphic parent-child relation is created between Setting and the parent/owning class.
|
58
|
+
Getters/setters are added through meta-programming-magic. If the setter is invoked on a unsafed parent then the setting is not saved until the parent is saved, else setting is saved upon creation (i.e. first time the setter is called) / change (subsequent calls).
|
59
|
+
The getters/setters can be used in standard AR validations, Rails mass assignments/form helpers and so on.
|
60
|
+
|
61
|
+
==Gotchas
|
62
|
+
* Values are stored as Strings in the DB. Values are converted with one of the formatters (depending on selected :type). If you try to store an unsupported type or anything other than the type you selected there might be an exception (i.e. if you try to store "foobar" as an :type => :int)
|
63
|
+
* Currently there are no length validations on the 'name' and 'value' column of Setting. Take care not to store values to big. Especially when using the array formatters (:floats, :ints, :strings)
|
64
|
+
|
65
|
+
|
66
|
+
==Example
|
67
|
+
<code>
|
68
|
+
class Foo < ActiveRecord::Base
|
69
|
+
has_setting(:string_setting)
|
70
|
+
has_setting(:another_string_setting, :type => :string)
|
71
|
+
has_setting(:int_setting, :type => :int)
|
72
|
+
has_setting(:float_setting, :type => :float, :default => 3.3)
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
foo = Foo.create
|
77
|
+
|
78
|
+
foo.string_setting
|
79
|
+
=> nil
|
80
|
+
foo.string_setting= 'a string'
|
81
|
+
foo.string_setting
|
82
|
+
=> 'a string'
|
83
|
+
|
84
|
+
foo.int_setting = 123
|
85
|
+
foo.int_setting
|
86
|
+
=> 123
|
87
|
+
foo.int_setting = '123'
|
88
|
+
foo.int_setting
|
89
|
+
=> 123
|
90
|
+
|
91
|
+
foo.float_setting
|
92
|
+
=> 3.3
|
93
|
+
foo.float_setting = nil
|
94
|
+
foo.float_setting
|
95
|
+
=> nil
|
96
|
+
|
97
|
+
</code>
|
98
|
+
|
99
|
+
|
100
|
+
==Todo
|
101
|
+
has_setting should stay as simple as possible... still some ideas are around:
|
102
|
+
* Custom formatter (to convert arbitrary objects, i.e. Date/Time/DateTime...)
|
103
|
+
* Add validation options
|
104
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'rake'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'jeweler'
|
5
|
+
Jeweler::Tasks.new do |s|
|
6
|
+
s.name = "has_setting"
|
7
|
+
s.summary = %Q{simple setting extension to AR}
|
8
|
+
s.email = "info@simplificator.com"
|
9
|
+
s.homepage = "http://github.com/simplificator/has_setting"
|
10
|
+
s.description = 'Stores settings as key/value pairs in a settings table and provides accessors for them on the owning object'
|
11
|
+
s.authors = ["Simplificator GmbH"]
|
12
|
+
s.files.exclude '**/*.sqlite3'
|
13
|
+
end
|
14
|
+
rescue LoadError
|
15
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
16
|
+
end
|
17
|
+
|
18
|
+
require 'rake/rdoctask'
|
19
|
+
Rake::RDocTask.new do |rdoc|
|
20
|
+
rdoc.rdoc_dir = 'rdoc'
|
21
|
+
rdoc.title = 'has_setting'
|
22
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
23
|
+
rdoc.rdoc_files.include('README*')
|
24
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
25
|
+
end
|
26
|
+
|
27
|
+
require 'rake/testtask'
|
28
|
+
Rake::TestTask.new(:test) do |t|
|
29
|
+
t.libs << 'lib' << 'test'
|
30
|
+
t.pattern = 'test/**/*_test.rb'
|
31
|
+
t.verbose = false
|
32
|
+
end
|
33
|
+
|
34
|
+
begin
|
35
|
+
require 'rcov/rcovtask'
|
36
|
+
Rcov::RcovTask.new do |t|
|
37
|
+
t.libs << 'test'
|
38
|
+
t.test_files = FileList['test/**/*_test.rb']
|
39
|
+
t.verbose = true
|
40
|
+
end
|
41
|
+
rescue LoadError
|
42
|
+
puts "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
43
|
+
end
|
44
|
+
|
45
|
+
begin
|
46
|
+
require 'cucumber/rake/task'
|
47
|
+
Cucumber::Rake::Task.new(:features)
|
48
|
+
rescue LoadError
|
49
|
+
puts "Cucumber is not available. In order to run features, you must: sudo gem install cucumber"
|
50
|
+
end
|
51
|
+
|
52
|
+
task :default => :test
|
data/VERSION.yml
CHANGED
data/lib/has_setting.rb
CHANGED
@@ -14,3 +14,5 @@ HasSetting::Formatters.register_formatter(:float, HasSetting::Formatters::FloatF
|
|
14
14
|
HasSetting::Formatters.register_formatter(:floats, HasSetting::Formatters::FloatFormatter.new)
|
15
15
|
HasSetting::Formatters.register_formatter(:int, HasSetting::Formatters::IntFormatter.new)
|
16
16
|
HasSetting::Formatters.register_formatter(:ints, HasSetting::Formatters::IntsFormatter.new)
|
17
|
+
HasSetting::Formatters.register_formatter(:boolean, HasSetting::Formatters::BooleanFormatter.new)
|
18
|
+
HasSetting::Formatters.register_formatter(:booleans, HasSetting::Formatters::BooleanFormatter.new)
|
@@ -36,13 +36,29 @@ module HasSetting
|
|
36
36
|
|
37
37
|
# Formatter for Strings
|
38
38
|
class StringFormatter < NilSafeFormatter
|
39
|
-
def
|
39
|
+
def safe_to_type(value)
|
40
40
|
value
|
41
41
|
end
|
42
42
|
def safe_to_s(value)
|
43
43
|
value.to_s
|
44
44
|
end
|
45
45
|
end
|
46
|
+
class BooleanFormatter < NilSafeFormatter
|
47
|
+
def safe_to_type(value)
|
48
|
+
value == '1'
|
49
|
+
end
|
50
|
+
def safe_to_s(value)
|
51
|
+
value ? '1' : '0'
|
52
|
+
end
|
53
|
+
end
|
54
|
+
class BooleansFormatter < NilSafeFormatter
|
55
|
+
def safe_to_type(value)
|
56
|
+
value.split(',').map() {|item| Formatters.for_type(:boolean).to_type(item)}
|
57
|
+
end
|
58
|
+
def safe_to_s(value)
|
59
|
+
Array(value).map() {|item| Formatters.for_type(:boolean).to_s(item)}.join(',')
|
60
|
+
end
|
61
|
+
end
|
46
62
|
|
47
63
|
class IntsFormatter < NilSafeFormatter
|
48
64
|
def safe_to_type(value)
|
@@ -2,7 +2,7 @@ require File.dirname(__FILE__) + '/../test_helper'
|
|
2
2
|
include HasSetting
|
3
3
|
class FormattersTest < Test::Unit::TestCase
|
4
4
|
def test_for_type
|
5
|
-
[:string, :float, :floats, :int, :ints, :strings].each do |symbol|
|
5
|
+
[:string, :float, :floats, :int, :ints, :strings, :boolean, :booleans].each do |symbol|
|
6
6
|
assert(Formatters.for_type(symbol), "No formatter for #{symbol}")
|
7
7
|
end
|
8
8
|
assert_raises(ArgumentError) do
|
@@ -26,6 +26,7 @@ class FormattersTest < Test::Unit::TestCase
|
|
26
26
|
assert_equal([',schni,schna,', 'bli', ',bla'], f.to_type('\,schni\,schna\,,bli,\,bla'))
|
27
27
|
assert_equal([',,,,', ',,,', ',,', ','], f.to_type('\,\,\,\,,\,\,\,,\,\,,\,'))
|
28
28
|
end
|
29
|
+
|
29
30
|
|
30
31
|
def test_string_formatter()
|
31
32
|
f = Formatters::StringFormatter.new
|
@@ -35,6 +36,18 @@ class FormattersTest < Test::Unit::TestCase
|
|
35
36
|
assert_equal('a', f.to_type('a'))
|
36
37
|
end
|
37
38
|
|
39
|
+
def test_boolean_formatter
|
40
|
+
f = Formatters::BooleanFormatter.new
|
41
|
+
assert_equal('1', f.to_s(''))
|
42
|
+
assert_equal('1', f.to_s(true))
|
43
|
+
assert_equal('0', f.to_s(false))
|
44
|
+
assert_equal(nil, f.to_s(nil))
|
45
|
+
|
46
|
+
assert_equal(true, f.to_type('1'))
|
47
|
+
assert_equal(false, f.to_type('0'))
|
48
|
+
assert_equal(nil, f.to_type(nil))
|
49
|
+
end
|
50
|
+
|
38
51
|
def test_int_formatter()
|
39
52
|
f = Formatters::IntFormatter.new
|
40
53
|
assert_raises(ArgumentError) do
|
@@ -107,5 +120,16 @@ class FormattersTest < Test::Unit::TestCase
|
|
107
120
|
assert_equal([1.2,1.3], f.to_type('1.2,1.3'))
|
108
121
|
assert_equal([1.2,1.3], f.to_type('1.2, 1.3'))
|
109
122
|
end
|
110
|
-
|
123
|
+
def test_booleans_formatter
|
124
|
+
f = Formatters::BooleansFormatter.new
|
125
|
+
assert_equal(nil, f.to_s(nil))
|
126
|
+
assert_equal('1', f.to_s(true))
|
127
|
+
assert_equal('1', f.to_s([true]))
|
128
|
+
assert_equal('1,0', f.to_s([true,false]))
|
129
|
+
|
130
|
+
assert_equal(nil, f.to_type(nil))
|
131
|
+
assert_equal([], f.to_type(''))
|
132
|
+
assert_equal([true], f.to_type('1'))
|
133
|
+
assert_equal([true, false], f.to_type('1,0'))
|
134
|
+
end
|
111
135
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simplificator-has_setting
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Simplificator GmbH
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-06-30 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -19,28 +19,26 @@ executables: []
|
|
19
19
|
|
20
20
|
extensions: []
|
21
21
|
|
22
|
-
extra_rdoc_files:
|
23
|
-
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README
|
24
24
|
files:
|
25
|
+
- Rakefile
|
25
26
|
- VERSION.yml
|
26
|
-
- lib/has_setting
|
27
|
+
- lib/has_setting.rb
|
27
28
|
- lib/has_setting/ar_extensions.rb
|
28
29
|
- lib/has_setting/formatters.rb
|
29
30
|
- lib/has_setting/setting.rb
|
30
|
-
- lib/has_setting.rb
|
31
31
|
- test/bar.rb
|
32
32
|
- test/baz.rb
|
33
33
|
- test/foo.rb
|
34
34
|
- test/test_helper.rb
|
35
|
-
- test/unit
|
36
35
|
- test/unit/formatters_test.rb
|
37
36
|
- test/unit/has_setting_test.rb
|
38
|
-
-
|
37
|
+
- README
|
39
38
|
has_rdoc: true
|
40
|
-
homepage: http://github.com/
|
39
|
+
homepage: http://github.com/simplificator/has_setting
|
41
40
|
post_install_message:
|
42
41
|
rdoc_options:
|
43
|
-
- --inline-source
|
44
42
|
- --charset=UTF-8
|
45
43
|
require_paths:
|
46
44
|
- lib
|
@@ -61,7 +59,12 @@ requirements: []
|
|
61
59
|
rubyforge_project:
|
62
60
|
rubygems_version: 1.2.0
|
63
61
|
signing_key:
|
64
|
-
specification_version:
|
62
|
+
specification_version: 3
|
65
63
|
summary: simple setting extension to AR
|
66
|
-
test_files:
|
67
|
-
|
64
|
+
test_files:
|
65
|
+
- test/bar.rb
|
66
|
+
- test/baz.rb
|
67
|
+
- test/foo.rb
|
68
|
+
- test/test_helper.rb
|
69
|
+
- test/unit/formatters_test.rb
|
70
|
+
- test/unit/has_setting_test.rb
|