ledermann-rails-settings 1.2.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
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