has_setting 0.5 → 0.6

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.
@@ -1,78 +1,72 @@
1
- ==What is it?
1
+ (This is now the official repository for the Simplificator [has_setting gem](https://github.com/simplificator/has_setting))
2
+
3
+ # What is it?
4
+
2
5
  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.
6
+ store settings in a separate settings table as key/value pairs where the key and value are stored as strings.
4
7
 
5
- ==History
6
- * 0.4.3:
7
- * Changed behaviour of :boolean formatters: Now they treat '0', 0, false, nil and '' as false, everything else as true
8
- This is not the same behaviour as ruby (treating only nil and false as false) but should help with input from web forms (i.e. checkboxes)
9
- If you want strict ruby boolean behaviour, then use :strict_boolean as :type
10
- * 0.4.2:
11
- * bug fixes for boolean types default values
12
- * 0.3.10:
13
- * added boolean and booleans formatters
14
- * 0.3.9:
15
- * added type :strings, :floats, :ints. They store the contents of an array as a comma separated string.
16
- * 0.3.8:
17
- * added dependent destroy option. no more zombie settings lingering around.
18
- * 0.3.7:
19
- * Gem is now built using jeweler... after messing around and bumping versions and getting
20
- strange errors, this is 'it works' feeling coming back
21
- * 0.3.4:
22
- * Added custom formatter support. no new formatters though...
23
- * 0.3.1:
24
- * Bug Fixed: has_many(:settings) is not added to ActiveRecord::Base but only to the classes with has_setting
25
- * Bug Fixed: options are not shared between classes
26
- * 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)
27
- * 0.2.x:
28
- * Added :default option
29
- * changed way settings are saved so that unsaved parents can have settings too
30
- * changed nameing scheme of setting names (incompatible with versions prior 0.2.x but since nobody uses the gem i dont care :-))
31
- * 0.1.x: First Version
32
8
 
9
+ # Installation
10
+
11
+ Add has_setting to your gemfile:
33
12
 
34
- ==Installation
35
- sudo gem install simplificator-has_setting
13
+ gem 'has_setting'
14
+
15
+ # Setup
36
16
 
37
- ==Setup
38
17
  * Add a migration that looks more or less like the one in <em>help/001_create_settings.rb</em>
39
18
  * Make sure the gem is loaded when your application starts
40
19
 
41
- ==Config
20
+ # Config
21
+
42
22
  The model you want to hold settings (i.e. User, Profile, ...):
43
- <tt>has_setting(:name_of_the_setting)</tt>
23
+
24
+ has_setting(:name_of_the_setting)
25
+
44
26
  This will create the following methods for you on the owner class:
45
- * <tt>name_of_the_setting=(value)</tt> a standard setter
46
- * <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())
27
+ * `name_of_the_setting=(value)` a standard setter
28
+ * `name_of_the_setting()` 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())
47
29
 
48
- <tt>has_setting(name, options)</tt> takes an optional hash of options. Following options are supported:
49
- <em>:type</em> allows you to convert the value:
50
- * <em>:string</em> (default) Uses the StringFormatter to convert from/to String (actually this formatter just leaves the value as it is)
51
- * <em>:int</em> Uses the IntFormatter to convert from/to int values.
52
- * <em>:boolean</em> Uses the BooleanFormatter to convert from/to boolean values; treating 0, '0', false, '' and nil as false.
53
- * <em>:strict_boolean</em> Uses the StrictBooleanFormatter to convert from/to boolean values; treating false, and nil as false.
54
- * <em>:float</em> Uses the FloatFormatter to convert from/to float values.
55
- * <em>:ints</em> Uses the IntsFormatter to convert from/to int[]
56
- * <em>:floats</em> Uses the FloatsFormatter to convert from/to float[]
57
- * <em>:strings</em> Uses the StringsFormatter to convert from/to string[]
58
- * <em>:booleans</em> Uses the BooleansFormatter to convert from/to boolean[]
59
- * <em>:strict_booleans</em> Uses the BooleansFormatter to convert from/to boolean[]
60
- <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.
61
-
62
-
63
-
64
- ==How it works
30
+ `has_setting(name, options)` takes an optional hash of options. Following options are supported:
31
+
32
+ *:type* allows you to convert the value:
33
+
34
+ * *:string* (default) Uses the StringFormatter to convert from/to String (actually this formatter just leaves the value as it is)
35
+ * *:int* Uses the IntFormatter to convert from/to int values.
36
+ * *:boolean* Uses the BooleanFormatter to convert from/to boolean values; treating 0, '0', false, '' and nil as false.
37
+ * *:strict_boolean* Uses the StrictBooleanFormatter to convert from/to boolean values; treating false, and nil as false.
38
+ * *:float* Uses the FloatFormatter to convert from/to float values.
39
+ * *:ints* Uses the IntsFormatter to convert from/to int[]
40
+ * *:floats* Uses the FloatsFormatter to convert from/to float[]
41
+ * *:strings* Uses the StringsFormatter to convert from/to string[]
42
+ * *:booleans* Uses the BooleansFormatter to convert from/to boolean[]
43
+ * *:strict_booleans* Uses the BooleansFormatter to convert from/to boolean[]
44
+ * *:default* 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.
45
+
46
+
47
+
48
+ # How it works
49
+
65
50
  A polymorphic parent-child relation is created between Setting and the parent/owning class.
66
51
  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).
67
52
  The getters/setters can be used in standard AR validations, Rails mass assignments/form helpers and so on.
68
53
 
69
- ==Gotchas
54
+
55
+ # Locale Awareness
56
+
57
+ has_setting has basic locale awareness. So when getting a setting, has_setting looks for the setting with the current locale. If it doesn't find it, it just grabs the first setting it finds, ignoring the locale.
58
+ When setting a setting, has_setting will look if a setting exists with the current locale and if not create a new settings record for the current locale.
59
+
60
+
61
+ # Gotchas
62
+
70
63
  * 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)
71
64
  * 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)
72
65
 
73
66
 
74
- ==Example
75
- <code>
67
+ # Example
68
+
69
+ ```
76
70
  class Foo < ActiveRecord::Base
77
71
  has_setting(:string_setting)
78
72
  has_setting(:another_string_setting, :type => :string)
@@ -101,12 +95,43 @@ foo.float_setting
101
95
  foo.float_setting = nil
102
96
  foo.float_setting
103
97
  => nil
104
-
105
- </code>
98
+ ```
106
99
 
107
100
 
108
- ==Todo
101
+ # Todo
102
+
109
103
  has_setting should stay as simple as possible... still some ideas are around:
110
104
  * Custom formatter (to convert arbitrary objects, i.e. Date/Time/DateTime...)
111
105
  * Add validation options
112
106
 
107
+ # History
108
+
109
+ * 0.5:
110
+ * Added basic locale awareness. If you update from a previous version, you need to add a locale column to the settings table.
111
+ * 0.4.3:
112
+ * Changed behaviour of :boolean formatters: Now they treat '0', 0, false, nil and '' as false, everything else as true
113
+ This is not the same behaviour as ruby (treating only nil and false as false) but should help with input from web forms (i.e. checkboxes)
114
+ If you want strict ruby boolean behaviour, then use :strict_boolean as :type
115
+ * 0.4.2:
116
+ * bug fixes for boolean types default values
117
+ * 0.3.10:
118
+ * added boolean and booleans formatters
119
+ * 0.3.9:
120
+ * added type :strings, :floats, :ints. They store the contents of an array as a comma separated string.
121
+ * 0.3.8:
122
+ * added dependent destroy option. no more zombie settings lingering around.
123
+ * 0.3.7:
124
+ * Gem is now built using jeweler... after messing around and bumping versions and getting
125
+ strange errors, this is 'it works' feeling coming back
126
+ * 0.3.4:
127
+ * Added custom formatter support. no new formatters though...
128
+ * 0.3.1:
129
+ * Bug Fixed: has_many(:settings) is not added to ActiveRecord::Base but only to the classes with has_setting
130
+ * Bug Fixed: options are not shared between classes
131
+ * 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)
132
+ * 0.2.x:
133
+ * Added :default option
134
+ * changed way settings are saved so that unsaved parents can have settings too
135
+ * changed nameing scheme of setting names (incompatible with versions prior 0.2.x but since nobody uses the gem i dont care :-))
136
+ * 0.1.x: First Version
137
+
data/lib/.DS_Store ADDED
Binary file
@@ -11,7 +11,7 @@ module HasSetting
11
11
  self.class_eval do
12
12
  unless @has_setting_options # define only once
13
13
  # AR association to settings
14
- has_many( :settings, :as => :owner, :class_name => 'HasSetting::Setting',
14
+ has_many( :settings, :as => :owner, :class_name => 'HasSetting::Setting',
15
15
  :foreign_key => :owner_id, :dependent => :destroy)
16
16
  after_save(:save_has_setting_association)
17
17
  @has_setting_options = {}
@@ -33,8 +33,7 @@ module HasSetting
33
33
 
34
34
  # default options
35
35
  type = options[:type] || :string # treat as string
36
- # default could be false, thats why we use has_key?
37
- default = options[:default] || (options.has_key?(:default) ? options[:default] : nil) # no default
36
+ options[:localize] ||= false
38
37
  self.has_setting_options[name] = options
39
38
 
40
39
  # setter
@@ -46,8 +45,8 @@ module HasSetting
46
45
  # getter
47
46
  define_method(name) do |*args|
48
47
  setting = read_setting(name)
49
- options = args.first || self.class.has_setting_options[name]
50
- return options[:default] if setting.nil?
48
+ options = args.first || has_setting_option(name)
49
+ return options[:default] if setting.nil?
51
50
  formatter = Formatters.for_type(options[:type] || type)
52
51
  formatter.to_type(setting.value)
53
52
  end
@@ -56,16 +55,36 @@ module HasSetting
56
55
 
57
56
  def write_setting(name, value)
58
57
  # find an existing setting or build a new one
59
- setting = self.settings.detect() {|item| item.name == name and item.locale.to_s == I18n.locale.to_s }
60
- setting = self.settings.build(:name => name, locale: I18n.locale.to_s) if setting.blank?
58
+ locale = localize?(name) ? I18n.locale : nil
59
+ setting = self.settings.detect() {|item| item.name == name and item.locale.to_s == locale.to_s }
60
+ setting = self.settings.build(:name => name, locale: locale) if setting.blank?
61
61
  setting.value = value
62
62
  end
63
63
 
64
64
  def read_setting(name)
65
- # use detect instead of SQL find. like this the 'cached' has_many-collection is inited
65
+ # use detect instead of SQL find. like this the 'cached' has_many-collection is inited
66
66
  # only once
67
- s = self.settings.detect() {|item| item.name == name and item.locale.to_s == I18n.locale.to_s} # first see if there is a setting with current locale
67
+ locale = localize?(name) ? I18n.locale.to_s : nil
68
+ s = self.settings.detect() {|item| item.name == name and item.locale.to_s == locale} # first see if there is a setting with current locale
68
69
  s ||= self.settings.detect() {|item| item.name == name} # then if not found, take the first setting with matching name (TODO: add locale fallbacks)
69
70
  s
70
71
  end
72
+
73
+ def localize? name
74
+ options = has_setting_option name
75
+ options ? options[:localize] : false
76
+ end
77
+
78
+ def has_setting_option name
79
+ klass = self.class
80
+ option = klass.has_setting_options ? klass.has_setting_options[name] : nil
81
+ while option.nil? and
82
+ klass.superclass != ActiveRecord::Base and
83
+ klass.superclass.respond_to?(:has_setting_options)
84
+ klass = klass.superclass
85
+ option = klass.has_setting_options[name]
86
+ end
87
+ option
88
+ end
89
+
71
90
  end
@@ -1,3 +1,3 @@
1
1
  module HasSetting
2
- VERSION = "0.5"
2
+ VERSION = "0.6"
3
3
  end
data/test/bar.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  class Bar < ActiveRecord::Base
2
- has_setting(:setting_1)
2
+ has_setting(:setting_1, localize: true)
3
3
  has_setting(:setting_2, :type => :int)
4
4
  end
data/test/test_helper.rb CHANGED
@@ -5,9 +5,9 @@ require 'test/unit'
5
5
  require File.dirname(__FILE__) + '/../lib/has_setting'
6
6
 
7
7
 
8
- ActiveRecord::Base.establish_connection(
9
- :adapter => 'sqlite3',
10
- :database => 'test.sqlite3',
8
+ ActiveRecord::Base.establish_connection(
9
+ :adapter => 'sqlite3',
10
+ :database => 'test.sqlite3',
11
11
  :timeout => 5000
12
12
  )
13
13
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: has_setting
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.5'
4
+ version: '0.6'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-04-10 00:00:00.000000000 Z
13
+ date: 2013-06-07 00:00:00.000000000 Z
14
14
  dependencies: []
15
15
  description: Stores settings as key/value pairs in a settings table and provides accessors
16
16
  for them on the owning object
@@ -22,11 +22,12 @@ extensions: []
22
22
  extra_rdoc_files: []
23
23
  files:
24
24
  - .gitignore
25
- - README
25
+ - README.md
26
26
  - Rakefile
27
27
  - VERSION.yml
28
28
  - has_setting.gemspec
29
29
  - help/001_create_settings.rb
30
+ - lib/.DS_Store
30
31
  - lib/has_setting.rb
31
32
  - lib/has_setting/ar_extensions.rb
32
33
  - lib/has_setting/formatters.rb
@@ -59,7 +60,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
59
60
  version: '0'
60
61
  requirements: []
61
62
  rubyforge_project:
62
- rubygems_version: 1.8.24
63
+ rubygems_version: 1.8.25
63
64
  signing_key:
64
65
  specification_version: 3
65
66
  summary: Simple setting extension to AR