ledermann-rails-settings 1.2.0 → 2.5.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.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.travis.yml +14 -6
  4. data/Gemfile +1 -1
  5. data/MIT-LICENSE +6 -5
  6. data/README.md +171 -158
  7. data/Rakefile +4 -9
  8. data/ci/Gemfile-rails-4-2 +7 -0
  9. data/ci/Gemfile-rails-5-0 +6 -0
  10. data/ci/Gemfile-rails-5-1 +6 -0
  11. data/ci/Gemfile-rails-5-2 +6 -0
  12. data/ci/Gemfile-rails-6-0 +6 -0
  13. data/lib/generators/rails_settings/migration/migration_generator.rb +23 -0
  14. data/lib/generators/rails_settings/migration/templates/migration.rb +21 -0
  15. data/lib/ledermann-rails-settings.rb +1 -0
  16. data/lib/rails-settings.rb +21 -5
  17. data/lib/rails-settings/base.rb +48 -0
  18. data/lib/rails-settings/configuration.rb +39 -0
  19. data/lib/rails-settings/scopes.rb +34 -0
  20. data/lib/rails-settings/setting_object.rb +84 -0
  21. data/lib/rails-settings/version.rb +2 -2
  22. data/rails-settings.gemspec +22 -21
  23. data/spec/configuration_spec.rb +120 -0
  24. data/spec/database.yml +3 -0
  25. data/spec/queries_spec.rb +101 -0
  26. data/spec/scopes_spec.rb +31 -0
  27. data/spec/serialize_spec.rb +40 -0
  28. data/spec/setting_object_spec.rb +153 -0
  29. data/spec/settings_spec.rb +248 -0
  30. data/spec/spec_helper.rb +111 -0
  31. data/spec/support/matchers/perform_queries.rb +22 -0
  32. data/spec/support/query_counter.rb +17 -0
  33. metadata +130 -118
  34. data/Changelog.md +0 -17
  35. data/ci/Gemfile.rails-2.3.x +0 -5
  36. data/ci/Gemfile.rails-3.0.x +0 -5
  37. data/ci/Gemfile.rails-3.1.x +0 -5
  38. data/ci/Gemfile.rails-3.2.x +0 -5
  39. data/init.rb +0 -1
  40. data/lib/rails-settings/active_record.rb +0 -38
  41. data/lib/rails-settings/null_store.rb +0 -48
  42. data/lib/rails-settings/scoped_settings.rb +0 -14
  43. data/lib/rails-settings/settings.rb +0 -142
  44. data/test/settings_test.rb +0 -252
  45. data/test/test_helper.rb +0 -34
@@ -1,5 +0,0 @@
1
- source :rubygems
2
-
3
- gem 'activerecord', '~> 2.3.14'
4
- gem 'sqlite3'
5
- gem 'rake'
@@ -1,5 +0,0 @@
1
- source :rubygems
2
-
3
- gem 'activerecord', '~> 3.0.12'
4
- gem 'sqlite3'
5
- gem 'rake'
@@ -1,5 +0,0 @@
1
- source :rubygems
2
-
3
- gem 'activerecord', '~> 3.1.4'
4
- gem 'sqlite3'
5
- gem 'rake'
@@ -1,5 +0,0 @@
1
- source :rubygems
2
-
3
- gem 'activerecord', '~> 3.2.2'
4
- gem 'sqlite3'
5
- gem 'rake'
data/init.rb DELETED
@@ -1 +0,0 @@
1
- require 'rails-settings'
@@ -1,38 +0,0 @@
1
- ActiveRecord::Base.class_eval do
2
- def self.has_settings
3
- class_eval do
4
- def settings
5
- ScopedSettings.for_target(self)
6
- end
7
-
8
- def self.settings
9
- ScopedSettings.for_target(self)
10
- end
11
-
12
- def settings=(hash)
13
- hash.each { |k,v| settings[k] = v }
14
- end
15
-
16
- after_destroy { |user| user.settings.target_scoped.delete_all }
17
-
18
- scope_method = ActiveRecord::VERSION::MAJOR < 3 ? :named_scope : :scope
19
-
20
- send scope_method, :with_settings, :joins => "JOIN settings ON (settings.target_id = #{self.table_name}.#{self.primary_key} AND
21
- settings.target_type = '#{self.base_class.name}')",
22
- :select => "DISTINCT #{self.table_name}.*"
23
-
24
- send scope_method, :with_settings_for, lambda { |var| { :joins => "JOIN settings ON (settings.target_id = #{self.table_name}.#{self.primary_key} AND
25
- settings.target_type = '#{self.base_class.name}') AND
26
- settings.var = '#{var}'" } }
27
-
28
- send scope_method, :without_settings, :joins => "LEFT JOIN settings ON (settings.target_id = #{self.table_name}.#{self.primary_key} AND
29
- settings.target_type = '#{self.base_class.name}')",
30
- :conditions => 'settings.id IS NULL'
31
-
32
- send scope_method, :without_settings_for, lambda { |var| { :joins => "LEFT JOIN settings ON (settings.target_id = #{self.table_name}.#{self.primary_key} AND
33
- settings.target_type = '#{self.base_class.name}') AND
34
- settings.var = '#{var}'",
35
- :conditions => 'settings.id IS NULL' } }
36
- end
37
- end
38
- end
@@ -1,48 +0,0 @@
1
- unless defined?(ActiveSupport::Cache::NullStore)
2
- # Copied from Rails 3
3
- # https://github.com/rails/rails/blob/master/activesupport/lib/active_support/cache/null_store.rb
4
- module ActiveSupport
5
- module Cache
6
- # A cache store implementation which doesn't actually store anything. Useful in
7
- # development and test environments where you don't want caching turned on but
8
- # need to go through the caching interface.
9
- #
10
- # This cache does implement the local cache strategy, so values will actually
11
- # be cached inside blocks that utilize this strategy. See
12
- # ActiveSupport::Cache::Strategy::LocalCache for more details.
13
- class NullStore < Store
14
- def initialize(options = nil)
15
- super()
16
- extend Strategy::LocalCache
17
- end
18
-
19
- def clear(options = nil)
20
- end
21
-
22
- def cleanup(options = nil)
23
- end
24
-
25
- def increment(name, amount = 1, options = nil)
26
- end
27
-
28
- def decrement(name, amount = 1, options = nil)
29
- end
30
-
31
- def delete_matched(matcher, options = nil)
32
- end
33
-
34
- protected
35
- def read_entry(key, options) # :nodoc:
36
- end
37
-
38
- def write_entry(key, entry, options) # :nodoc:
39
- true
40
- end
41
-
42
- def delete_entry(key, options) # :nodoc:
43
- false
44
- end
45
- end
46
- end
47
- end
48
- end
@@ -1,14 +0,0 @@
1
- class ScopedSettings < Settings
2
- def self.for_target(target)
3
- @target = target
4
- self
5
- end
6
-
7
- def self.target_id
8
- @target.is_a?(Class) ? nil : @target.id
9
- end
10
-
11
- def self.target_type
12
- @target.is_a?(Class) ? @target.name : @target.class.base_class.to_s
13
- end
14
- end
@@ -1,142 +0,0 @@
1
- class Settings < ActiveRecord::Base
2
- class SettingNotFound < RuntimeError; end
3
-
4
- cattr_accessor :defaults
5
- self.defaults = {}.with_indifferent_access
6
-
7
- # cache must follow the contract of ActiveSupport::Cache. Defaults to no-op.
8
- cattr_accessor :cache
9
- self.cache = ActiveSupport::Cache::NullStore.new
10
-
11
- # options passed to cache.fetch() and cache.write(). example: {:expires_in => 5.minutes}
12
- cattr_accessor :cache_options
13
- self.cache_options = {}
14
-
15
- def self.cache_key(var_name)
16
- [target_id, target_type, var_name].compact.join("::")
17
- end
18
-
19
- # Support old plugin
20
- if defined?(SettingsDefaults::DEFAULTS)
21
- self.defaults = SettingsDefaults::DEFAULTS.with_indifferent_access
22
- end
23
-
24
- #get or set a variable with the variable as the called method
25
- def self.method_missing(method, *args)
26
- if self.respond_to?(method)
27
- super
28
- else
29
- method_name = method.to_s
30
-
31
- #set a value for a variable
32
- if method_name =~ /=$/
33
- var_name = method_name.gsub('=', '')
34
- value = args.first
35
- self[var_name] = value
36
-
37
- #retrieve a value
38
- else
39
- self[method_name]
40
-
41
- end
42
- end
43
- end
44
-
45
- #destroy the specified settings record
46
- def self.destroy(var_name)
47
- var_name = var_name.to_s
48
- begin
49
- target(var_name).destroy
50
- cache.delete(cache_key(var_name))
51
- true
52
- rescue NoMethodError
53
- raise SettingNotFound, "Setting variable \"#{var_name}\" not found"
54
- end
55
- end
56
-
57
- def self.delete_all(conditions = nil)
58
- cache.clear
59
- super
60
- end
61
-
62
- #retrieve all settings as a hash (optionally starting with a given namespace)
63
- def self.all(starting_with=nil)
64
- options = starting_with ? { :conditions => "var LIKE '#{starting_with}%'"} : {}
65
- vars = target_scoped.find(:all, {:select => 'var, value'}.merge(options))
66
-
67
- result = {}
68
- vars.each do |record|
69
- result[record.var] = record.value
70
- end
71
- defaults = @@defaults.select{ |k, v| k =~ /^#{starting_with}/ }
72
- defaults = Hash[defaults] if defaults.is_a?(Array)
73
- defaults.merge(result).with_indifferent_access
74
- end
75
-
76
- #get a setting value by [] notation
77
- def self.[](var_name)
78
- cache.fetch(cache_key(var_name), cache_options) do
79
- if var = target(var_name)
80
- var.value
81
- else
82
- if target_id.nil?
83
- @@defaults[var_name.to_s]
84
- else
85
- target_type.constantize.settings[var_name.to_s]
86
- end
87
- end
88
- end
89
- end
90
-
91
- #set a setting value by [] notation
92
- def self.[]=(var_name, value)
93
- record = target_scoped.find_or_initialize_by_var(var_name.to_s)
94
- record.value = value
95
- record.save!
96
- cache.write(cache_key(var_name), value, cache_options)
97
- value
98
- end
99
-
100
- def self.merge!(var_name, hash_value)
101
- raise ArgumentError unless hash_value.is_a?(Hash)
102
-
103
- old_value = self[var_name] || {}
104
- raise TypeError, "Existing value is not a hash, can't merge!" unless old_value.is_a?(Hash)
105
-
106
- new_value = old_value.merge(hash_value)
107
- self[var_name] = new_value if new_value != old_value
108
-
109
- new_value
110
- end
111
-
112
- def self.target(var_name)
113
- target_scoped.find_by_var(var_name.to_s)
114
- end
115
-
116
- #get the value field, YAML decoded
117
- def value
118
- YAML::load(self[:value])
119
- end
120
-
121
- #set the value field, YAML encoded
122
- def value=(new_value)
123
- self[:value] = new_value.to_yaml
124
- end
125
-
126
- def self.target_scoped
127
- Settings.scoped_by_target_type_and_target_id(target_type, target_id)
128
- end
129
-
130
- #Deprecated!
131
- def self.reload # :nodoc:
132
- self
133
- end
134
-
135
- def self.target_id
136
- nil
137
- end
138
-
139
- def self.target_type
140
- nil
141
- end
142
- end
@@ -1,252 +0,0 @@
1
- require 'test_helper'
2
-
3
- class SettingsTest < Test::Unit::TestCase
4
- setup_db
5
-
6
- def setup
7
- Settings.create!(:var => 'test', :value => 'foo')
8
- Settings.create!(:var => 'test2', :value => 'bar')
9
-
10
- # Reset defaults
11
- Settings.defaults = {}.with_indifferent_access
12
- end
13
-
14
- def teardown
15
- User.delete_all
16
- Settings.delete_all
17
- end
18
-
19
- def test_defaults
20
- Settings.defaults[:foo] = 'default foo'
21
-
22
- assert_nil Settings.target(:foo)
23
- assert_equal 'default foo', Settings.foo
24
-
25
- Settings.foo = 'bar'
26
- assert_equal 'bar', Settings.foo
27
- assert_not_nil Settings.target(:foo)
28
- end
29
-
30
- def tests_defaults_true
31
- Settings.defaults[:foo] = true
32
- assert_equal true, Settings.foo
33
- end
34
-
35
- def tests_defaults_false
36
- Settings.defaults[:foo] = false
37
- assert_equal false, Settings.foo
38
- end
39
-
40
- def test_get
41
- assert_setting 'foo', :test
42
- assert_setting 'bar', :test2
43
- end
44
-
45
- def test_update
46
- assert_assign_setting '321', :test
47
- end
48
-
49
- def test_create
50
- assert_assign_setting '123', :onetwothree
51
- end
52
-
53
- def test_complex_serialization
54
- complex = [1, '2', {:three => true}]
55
- Settings.complex = complex
56
- assert_equal complex, Settings.complex
57
- end
58
-
59
- def test_serialization_of_float
60
- Settings.float = 0.01
61
- Settings.reload
62
- assert_equal 0.01, Settings.float
63
- assert_equal 0.02, Settings.float * 2
64
- end
65
-
66
- def test_target_scope
67
- user1 = User.create! :name => 'First user'
68
- user2 = User.create! :name => 'Second user'
69
-
70
- assert_assign_setting 1, :one, user1
71
- assert_assign_setting 2, :two, user2
72
-
73
- assert_setting 1, :one, user1
74
- assert_setting 2, :two, user2
75
-
76
- assert_setting nil, :one
77
- assert_setting nil, :two
78
-
79
- assert_setting nil, :two, user1
80
- assert_setting nil, :one, user2
81
-
82
- assert_equal({ "one" => 1}, user1.settings.all('one'))
83
- assert_equal({ "two" => 2}, user2.settings.all('two'))
84
- assert_equal({ "one" => 1}, user1.settings.all('o'))
85
- assert_equal({}, user1.settings.all('non_existing_var'))
86
- end
87
-
88
- def test_named_scope
89
- user_without_settings = User.create! :name => 'User without settings'
90
- user_with_settings = User.create! :name => 'User with settings'
91
- user_with_settings.settings.one = '1'
92
- user_with_settings.settings.two = '2'
93
-
94
- assert_equal [user_with_settings], User.with_settings
95
- assert_equal [user_with_settings], User.with_settings_for('one')
96
- assert_equal [user_with_settings], User.with_settings_for('two')
97
- assert_equal [], User.with_settings_for('foo')
98
-
99
- assert_equal [user_without_settings], User.without_settings
100
- assert_equal [user_without_settings], User.without_settings_for('one')
101
- assert_equal [user_without_settings], User.without_settings_for('two')
102
- assert_equal [user_without_settings, user_with_settings], User.without_settings_for('foo')
103
- end
104
-
105
- def test_delete_settings_after_destroying_target
106
- user1 = User.create! :name => 'Mr. Foo'
107
- user2 = User.create! :name => 'Mr. Bar'
108
- user1.settings.example = 42
109
- user2.settings.example = 43
110
-
111
- before_count = Settings.count
112
- user1.destroy
113
- assert_equal before_count - 1, Settings.count
114
-
115
- before_count = Settings.count
116
- user2.destroy
117
- assert_equal before_count - 1, Settings.count
118
- end
119
-
120
- def test_all
121
- assert_equal({ "test2" => "bar", "test" => "foo" }, Settings.all)
122
- assert_equal({ "test2" => "bar" }, Settings.all('test2'))
123
- assert_equal({ "test2" => "bar", "test" => "foo" }, Settings.all('test'))
124
- assert_equal({}, Settings.all('non_existing_var'))
125
- end
126
-
127
- def test_merge
128
- assert_raise(TypeError) do
129
- Settings.merge! :test, { :a => 1 }
130
- end
131
-
132
- Settings[:hash] = { :one => 1 }
133
- Settings.merge! :hash, { :two => 2 }
134
- assert_equal({ :one => 1, :two => 2 }, Settings[:hash])
135
-
136
- assert_raise(ArgumentError) do
137
- Settings.merge! :hash, 123
138
- end
139
-
140
- Settings.merge! :empty_hash, { :two => 2 }
141
- assert_equal({ :two => 2 }, Settings[:empty_hash])
142
- end
143
-
144
- def test_destroy
145
- Settings.destroy :test
146
- assert_equal nil, Settings.test
147
-
148
- assert_raise(Settings::SettingNotFound) do
149
- Settings.destroy :unknown
150
- end
151
- end
152
-
153
- def test_false
154
- Settings.test3 = false
155
- assert_setting(false, 'test3')
156
-
157
- Settings.destroy :test3
158
- assert_setting(nil, 'test3')
159
- end
160
-
161
- def test_class_level_settings
162
- assert_equal User.settings.name, "ScopedSettings"
163
- end
164
-
165
- def test_object_inherits_class_settings_before_default
166
- Settings.defaults[:foo] = 'global default'
167
- User.settings.foo = 'model default'
168
-
169
- user = User.create! :name => 'Dwight'
170
-
171
- assert_equal user.settings.foo, 'model default'
172
- assert_equal 'global default', Settings.foo
173
- end
174
-
175
- def test_class_inherits_default_settings
176
- Settings.defaults[:foo] = 'bar'
177
- assert_equal User.settings.foo, 'bar'
178
- end
179
-
180
- def test_sets_settings_with_hash
181
- user = User.create! :name => 'Mr. Foo'
182
- user.settings[:one] = '1'
183
- user.settings[:two] = '2'
184
- user.settings = { :two => '2a', :three => '3' }
185
-
186
- assert_equal '1', user.settings[:one] # ensure existing settings remain intact
187
- assert_equal '2a', user.settings[:two] # ensure settings are properly overwritten
188
- assert_equal '3', user.settings[:three] # ensure new setting are created
189
- end
190
-
191
- def test_all_includes_defaults
192
- Settings.defaults[:foo] = 'bar'
193
- user = User.create! :name => 'Mr. Foo'
194
- assert_equal({ 'foo' => 'bar' }, user.settings.all)
195
- end
196
-
197
- private
198
- def assert_setting(value, key, scope_target=nil)
199
- key = key.to_sym
200
-
201
- if scope_target
202
- assert_equal value, scope_target.instance_eval("settings.#{key}")
203
- assert_equal value, scope_target.settings[key.to_sym]
204
- assert_equal value, scope_target.settings[key.to_s]
205
- else
206
- assert_equal value, eval("Settings.#{key}")
207
- assert_equal value, Settings[key.to_sym]
208
- assert_equal value, Settings[key.to_s]
209
- end
210
- end
211
-
212
- def assert_assign_setting(value, key, scope_target=nil)
213
- key = key.to_sym
214
-
215
- if scope_target
216
- assert_equal value, (scope_target.settings[key] = value)
217
- assert_setting value, key, scope_target
218
- scope_target.settings[key] = nil
219
-
220
- assert_equal value, (scope_target.settings[key.to_s] = value)
221
- assert_setting value, key, scope_target
222
- else
223
- assert_equal value, (Settings[key] = value)
224
- assert_setting value, key
225
- Settings[key] = nil
226
-
227
- assert_equal value, (Settings[key.to_s] = value)
228
- assert_setting value, key
229
- end
230
- end
231
- end
232
-
233
- class CachedSettingsTest < SettingsTest
234
- def setup
235
- Settings.cache = ActiveSupport::Cache::MemoryStore.new
236
- Settings.cache_options = { :expires_in => 5.minutes }
237
- super
238
- end
239
-
240
- def test_caching_is_in_place
241
- Settings.progress = "boing"
242
- Settings.connection.execute("delete from settings")
243
- assert_equal "boing", Settings.progress
244
- Settings.cache.clear
245
- assert_nil Settings.progress
246
- end
247
-
248
- def teardown
249
- Settings.cache.clear
250
- super
251
- end
252
- end