ledermann-rails-settings 1.2.1 → 2.0.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.
@@ -0,0 +1,18 @@
1
+ RSpec::Matchers.define :perform_queries do |expected|
2
+ match do |block|
3
+ query_count(&block) == expected
4
+ end
5
+
6
+ failure_message_for_should do |actual|
7
+ "Expected to run #{expected} queries, got #{@counter.query_count}"
8
+ end
9
+
10
+ def query_count(&block)
11
+ @counter = ActiveRecord::QueryCounter.new
12
+ ActiveSupport::Notifications.subscribe('sql.active_record', @counter.to_proc)
13
+ yield
14
+ ActiveSupport::Notifications.unsubscribe(@counter.to_proc)
15
+
16
+ @counter.query_count
17
+ end
18
+ end
@@ -0,0 +1,17 @@
1
+ module ActiveRecord
2
+ class QueryCounter
3
+ attr_reader :query_count
4
+
5
+ def initialize
6
+ @query_count = 0
7
+ end
8
+
9
+ def to_proc
10
+ lambda(&method(:callback))
11
+ end
12
+
13
+ def callback(name, start, finish, message_id, values)
14
+ @query_count += 1 unless %w(CACHE SCHEMA).include?(values[:name]) || values[:sql] == 'begin transaction' || values[:sql] == 'commit transaction'
15
+ end
16
+ end
17
+ end
metadata CHANGED
@@ -1,99 +1,72 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ledermann-rails-settings
3
3
  version: !ruby/object:Gem::Version
4
- prerelease:
5
- version: 1.2.1
4
+ version: 2.0.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Georg Ledermann
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-02-09 00:00:00.000000000 Z
11
+ date: 2013-03-07 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
- prerelease: false
16
- version_requirements: !ruby/object:Gem::Requirement
17
- requirements:
18
- - - ! '>='
19
- - !ruby/object:Gem::Version
20
- version: '2.3'
21
- none: false
22
- type: :runtime
23
14
  name: activerecord
24
15
  requirement: !ruby/object:Gem::Requirement
25
16
  requirements:
26
- - - ! '>='
17
+ - - ~>
27
18
  - !ruby/object:Gem::Version
28
- version: '2.3'
29
- none: false
30
- - !ruby/object:Gem::Dependency
19
+ version: '3.1'
20
+ type: :runtime
31
21
  prerelease: false
32
22
  version_requirements: !ruby/object:Gem::Requirement
33
23
  requirements:
34
- - - ! '>='
24
+ - - ~>
35
25
  - !ruby/object:Gem::Version
36
- version: '0'
37
- none: false
38
- type: :development
26
+ version: '3.1'
27
+ - !ruby/object:Gem::Dependency
39
28
  name: rake
40
29
  requirement: !ruby/object:Gem::Requirement
41
30
  requirements:
42
- - - ! '>='
31
+ - - ~>
43
32
  - !ruby/object:Gem::Version
44
- version: '0'
45
- none: false
46
- - !ruby/object:Gem::Dependency
33
+ version: '10.0'
34
+ type: :development
47
35
  prerelease: false
48
36
  version_requirements: !ruby/object:Gem::Requirement
49
37
  requirements:
50
- - - ! '>='
38
+ - - ~>
51
39
  - !ruby/object:Gem::Version
52
- version: '0'
53
- none: false
54
- type: :development
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
55
42
  name: sqlite3
56
43
  requirement: !ruby/object:Gem::Requirement
57
44
  requirements:
58
- - - ! '>='
45
+ - - ~>
59
46
  - !ruby/object:Gem::Version
60
- version: '0'
61
- none: false
62
- - !ruby/object:Gem::Dependency
47
+ version: '1.3'
48
+ type: :development
63
49
  prerelease: false
64
50
  version_requirements: !ruby/object:Gem::Requirement
65
51
  requirements:
66
- - - ! '>='
52
+ - - ~>
67
53
  - !ruby/object:Gem::Version
68
- version: '0'
69
- none: false
70
- type: :development
71
- name: rake
54
+ version: '1.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
72
57
  requirement: !ruby/object:Gem::Requirement
73
58
  requirements:
74
- - - ! '>='
59
+ - - ~>
75
60
  - !ruby/object:Gem::Version
76
- version: '0'
77
- none: false
78
- - !ruby/object:Gem::Dependency
61
+ version: '2.13'
62
+ type: :development
79
63
  prerelease: false
80
64
  version_requirements: !ruby/object:Gem::Requirement
81
65
  requirements:
82
- - - ! '>='
83
- - !ruby/object:Gem::Version
84
- version: '0'
85
- none: false
86
- type: :development
87
- name: sqlite3
88
- requirement: !ruby/object:Gem::Requirement
89
- requirements:
90
- - - ! '>='
66
+ - - ~>
91
67
  - !ruby/object:Gem::Version
92
- version: '0'
93
- none: false
94
- description: Ruby Gem that makes managing a table of key/value pairs easy. Think of
95
- it like a Hash stored in you database, that uses simple ActiveRecord like methods
96
- for manipulation.
68
+ version: '2.13'
69
+ description: Settings gem for Ruby on Rails
97
70
  email:
98
71
  - mail@georg-ledermann.de
99
72
  executables: []
@@ -107,43 +80,57 @@ files:
107
80
  - MIT-LICENSE
108
81
  - README.md
109
82
  - Rakefile
110
- - ci/Gemfile.rails-2.3.x
111
- - ci/Gemfile.rails-3.0.x
112
83
  - ci/Gemfile.rails-3.1.x
113
84
  - ci/Gemfile.rails-3.2.x
114
- - init.rb
85
+ - lib/generators/rails_settings/migration/migration_generator.rb
86
+ - lib/generators/rails_settings/migration/templates/migration.rb
115
87
  - lib/rails-settings.rb
116
- - lib/rails-settings/active_record.rb
117
- - lib/rails-settings/scoped_settings.rb
118
- - lib/rails-settings/settings.rb
88
+ - lib/rails-settings/base.rb
89
+ - lib/rails-settings/configuration.rb
90
+ - lib/rails-settings/scopes.rb
91
+ - lib/rails-settings/setting_object.rb
119
92
  - lib/rails-settings/version.rb
120
93
  - rails-settings.gemspec
121
- - test/settings_test.rb
122
- - test/test_helper.rb
94
+ - spec/configuration_spec.rb
95
+ - spec/queries_spec.rb
96
+ - spec/scopes_spec.rb
97
+ - spec/serialize_spec.rb
98
+ - spec/setting_object_spec.rb
99
+ - spec/settings_spec.rb
100
+ - spec/spec_helper.rb
101
+ - spec/support/matchers/perform_queries.rb
102
+ - spec/support/query_counter.rb
123
103
  homepage: https://github.com/ledermann/rails-settings
124
104
  licenses: []
105
+ metadata: {}
125
106
  post_install_message:
126
107
  rdoc_options: []
127
108
  require_paths:
128
109
  - lib
129
110
  required_ruby_version: !ruby/object:Gem::Requirement
130
111
  requirements:
131
- - - ! '>='
112
+ - - '>='
132
113
  - !ruby/object:Gem::Version
133
114
  version: '0'
134
- none: false
135
115
  required_rubygems_version: !ruby/object:Gem::Requirement
136
116
  requirements:
137
- - - ! '>='
117
+ - - '>='
138
118
  - !ruby/object:Gem::Version
139
119
  version: '0'
140
- none: false
141
120
  requirements: []
142
- rubyforge_project: ledermann-rails-settings
143
- rubygems_version: 1.8.25
121
+ rubyforge_project:
122
+ rubygems_version: 2.0.2
144
123
  signing_key:
145
- specification_version: 3
146
- summary: Settings management for ActiveRecord objects
124
+ specification_version: 4
125
+ summary: 'Handling settings for ActiveRecord objects by storing them as serialized
126
+ Hash in a separate database table. Optional: Defaults and Namespaces.'
147
127
  test_files:
148
- - test/settings_test.rb
149
- - test/test_helper.rb
128
+ - spec/configuration_spec.rb
129
+ - spec/queries_spec.rb
130
+ - spec/scopes_spec.rb
131
+ - spec/serialize_spec.rb
132
+ - spec/setting_object_spec.rb
133
+ - spec/settings_spec.rb
134
+ - spec/spec_helper.rb
135
+ - spec/support/matchers/perform_queries.rb
136
+ - spec/support/query_counter.rb
@@ -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'
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,20 +0,0 @@
1
- class ScopedSettings < Settings
2
-
3
- @klasses = {}
4
-
5
- def self.for_target(target)
6
- @klasses[target] ||= self.dup.instance_eval do
7
- def name; "ScopedSettings"; end # Required by ActiveModel::Naming
8
- @target = target
9
- self
10
- end
11
- end
12
-
13
- def self.target_id
14
- @target.is_a?(Class) ? nil : @target.id
15
- end
16
-
17
- def self.target_type
18
- @target.is_a?(Class) ? @target.name : @target.class.base_class.to_s
19
- end
20
- end
@@ -1,121 +0,0 @@
1
- class Settings < ActiveRecord::Base
2
- class SettingNotFound < RuntimeError; end
3
-
4
- def self.defaults
5
- Thread.current[:rails_settings_defaults] ||= {}.with_indifferent_access
6
- end
7
-
8
- def self.defaults=(value)
9
- Thread.current[:rails_settings_defaults] = value
10
- end
11
-
12
- #get or set a variable with the variable as the called method
13
- def self.method_missing(method, *args)
14
- if self.respond_to?(method)
15
- super
16
- else
17
- method_name = method.to_s
18
-
19
- #set a value for a variable
20
- if method_name =~ /=$/
21
- var_name = method_name.gsub('=', '')
22
- value = args.first
23
- self[var_name] = value
24
-
25
- #retrieve a value
26
- else
27
- self[method_name]
28
-
29
- end
30
- end
31
- end
32
-
33
- #destroy the specified settings record
34
- def self.destroy(var_name)
35
- var_name = var_name.to_s
36
- begin
37
- target(var_name).destroy
38
- true
39
- rescue NoMethodError
40
- raise SettingNotFound, "Setting variable \"#{var_name}\" not found"
41
- end
42
- end
43
-
44
- #retrieve all settings as a hash (optionally starting with a given namespace)
45
- def self.all(starting_with=nil)
46
- options = starting_with ? { :conditions => "var LIKE '#{starting_with}%'"} : {}
47
- vars = target_scoped.find(:all, {:select => 'var, value'}.merge(options))
48
-
49
- result = {}
50
- vars.each do |record|
51
- result[record.var] = record.value
52
- end
53
- selected_defaults = defaults.select{ |k, v| k =~ /^#{starting_with}/ }
54
- selected_defaults = Hash[selected_defaults] if selected_defaults.is_a?(Array)
55
- selected_defaults.merge(result).with_indifferent_access
56
- end
57
-
58
- #get a setting value by [] notation
59
- def self.[](var_name)
60
- if var = target(var_name)
61
- var.value
62
- else
63
- if target_id.nil?
64
- defaults[var_name.to_s]
65
- else
66
- target_type.constantize.settings[var_name.to_s]
67
- end
68
- end
69
- end
70
-
71
- #set a setting value by [] notation
72
- def self.[]=(var_name, value)
73
- record = target_scoped.find_or_initialize_by_var(var_name.to_s)
74
- record.value = value
75
- record.save!
76
- value
77
- end
78
-
79
- def self.merge!(var_name, hash_value)
80
- raise ArgumentError unless hash_value.is_a?(Hash)
81
-
82
- old_value = self[var_name] || {}
83
- raise TypeError, "Existing value is not a hash, can't merge!" unless old_value.is_a?(Hash)
84
-
85
- new_value = old_value.merge(hash_value)
86
- self[var_name] = new_value if new_value != old_value
87
-
88
- new_value
89
- end
90
-
91
- def self.target(var_name)
92
- target_scoped.find_by_var(var_name.to_s)
93
- end
94
-
95
- #get the value field, YAML decoded
96
- def value
97
- YAML::load(self[:value])
98
- end
99
-
100
- #set the value field, YAML encoded
101
- def value=(new_value)
102
- self[:value] = new_value.to_yaml
103
- end
104
-
105
- def self.target_scoped
106
- Settings.scoped_by_target_type_and_target_id(target_type, target_id)
107
- end
108
-
109
- #Deprecated!
110
- def self.reload # :nodoc:
111
- self
112
- end
113
-
114
- def self.target_id
115
- nil
116
- end
117
-
118
- def self.target_type
119
- nil
120
- end
121
- end
@@ -1,258 +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_target_scope_is_instance_safe
89
- user1 = User.create! :name => 'First user'
90
- user2 = User.create! :name => 'Second user'
91
-
92
- assert_assign_setting 'Foo one', :foo, user1
93
- assert_assign_setting 'Foo two', :foo, user2
94
-
95
- settings_1 = user1.settings
96
- settings_2 = user2.settings
97
- assert_equal 'Foo one', settings_1.foo
98
- end
99
-
100
- def test_named_scope
101
- user_without_settings = User.create! :name => 'User without settings'
102
- user_with_settings = User.create! :name => 'User with settings'
103
- user_with_settings.settings.one = '1'
104
- user_with_settings.settings.two = '2'
105
-
106
- assert_equal [user_with_settings], User.with_settings
107
- assert_equal [user_with_settings], User.with_settings_for('one')
108
- assert_equal [user_with_settings], User.with_settings_for('two')
109
- assert_equal [], User.with_settings_for('foo')
110
-
111
- assert_equal [user_without_settings], User.without_settings
112
- assert_equal [user_without_settings], User.without_settings_for('one')
113
- assert_equal [user_without_settings], User.without_settings_for('two')
114
- assert_equal [user_without_settings, user_with_settings], User.without_settings_for('foo')
115
- end
116
-
117
- def test_delete_settings_after_destroying_target
118
- user1 = User.create! :name => 'Mr. Foo'
119
- user2 = User.create! :name => 'Mr. Bar'
120
- user1.settings.example = 42
121
- user2.settings.example = 43
122
-
123
- before_count = Settings.count
124
- user1.destroy
125
- assert_equal before_count - 1, Settings.count
126
-
127
- before_count = Settings.count
128
- user2.destroy
129
- assert_equal before_count - 1, Settings.count
130
- end
131
-
132
- def test_all
133
- assert_equal({ "test2" => "bar", "test" => "foo" }, Settings.all)
134
- assert_equal({ "test2" => "bar" }, Settings.all('test2'))
135
- assert_equal({ "test2" => "bar", "test" => "foo" }, Settings.all('test'))
136
- assert_equal({}, Settings.all('non_existing_var'))
137
- end
138
-
139
- def test_merge
140
- assert_raise(TypeError) do
141
- Settings.merge! :test, { :a => 1 }
142
- end
143
-
144
- Settings[:hash] = { :one => 1 }
145
- Settings.merge! :hash, { :two => 2 }
146
- assert_equal({ :one => 1, :two => 2 }, Settings[:hash])
147
-
148
- assert_raise(ArgumentError) do
149
- Settings.merge! :hash, 123
150
- end
151
-
152
- Settings.merge! :empty_hash, { :two => 2 }
153
- assert_equal({ :two => 2 }, Settings[:empty_hash])
154
- end
155
-
156
- def test_association_merge
157
- user = User.create! :name => 'Mr. Foo'
158
- user.settings.merge! :foo, { :one => 1, :two => 2}
159
-
160
- assert_equal({:one => 1, :two => 2}, user.settings.foo)
161
- end
162
-
163
- def test_destroy
164
- Settings.destroy :test
165
- assert_equal nil, Settings.test
166
-
167
- assert_raise(Settings::SettingNotFound) do
168
- Settings.destroy :unknown
169
- end
170
- end
171
-
172
- def test_false
173
- Settings.test3 = false
174
- assert_setting(false, 'test3')
175
-
176
- Settings.destroy :test3
177
- assert_setting(nil, 'test3')
178
- end
179
-
180
- def test_class_level_settings
181
- assert_equal User.settings.name, "ScopedSettings"
182
- end
183
-
184
- def test_object_inherits_class_settings_before_default
185
- Settings.defaults[:foo] = 'global default'
186
- User.settings.foo = 'model default'
187
-
188
- user = User.create! :name => 'Dwight'
189
-
190
- assert_equal user.settings.foo, 'model default'
191
- assert_equal 'global default', Settings.foo
192
- end
193
-
194
- def test_class_inherits_default_settings
195
- Settings.defaults[:foo] = 'bar'
196
- assert_equal User.settings.foo, 'bar'
197
- end
198
-
199
- def test_sets_settings_with_hash
200
- user = User.create! :name => 'Mr. Foo'
201
- user.settings[:one] = '1'
202
- user.settings[:two] = '2'
203
- user.settings = { :two => '2a', :three => '3' }
204
-
205
- assert_equal '1', user.settings[:one] # ensure existing settings remain intact
206
- assert_equal '2a', user.settings[:two] # ensure settings are properly overwritten
207
- assert_equal '3', user.settings[:three] # ensure new setting are created
208
- end
209
-
210
- def test_all_includes_defaults
211
- Settings.defaults[:foo] = 'bar'
212
- user = User.create! :name => 'Mr. Foo'
213
- assert_equal({ 'foo' => 'bar' }, user.settings.all)
214
- end
215
-
216
- def test_issue_18
217
- Settings.one = 'value1'
218
- User.settings.two = 'value2'
219
-
220
- assert_equal({'two' => 'value2'}, User.settings.all)
221
- end
222
-
223
-
224
- private
225
- def assert_setting(value, key, scope_target=nil)
226
- key = key.to_sym
227
-
228
- if scope_target
229
- assert_equal value, scope_target.instance_eval("settings.#{key}")
230
- assert_equal value, scope_target.settings[key.to_sym]
231
- assert_equal value, scope_target.settings[key.to_s]
232
- else
233
- assert_equal value, eval("Settings.#{key}")
234
- assert_equal value, Settings[key.to_sym]
235
- assert_equal value, Settings[key.to_s]
236
- end
237
- end
238
-
239
- def assert_assign_setting(value, key, scope_target=nil)
240
- key = key.to_sym
241
-
242
- if scope_target
243
- assert_equal value, (scope_target.settings[key] = value)
244
- assert_setting value, key, scope_target
245
- scope_target.settings[key] = nil
246
-
247
- assert_equal value, (scope_target.settings[key.to_s] = value)
248
- assert_setting value, key, scope_target
249
- else
250
- assert_equal value, (Settings[key] = value)
251
- assert_setting value, key
252
- Settings[key] = nil
253
-
254
- assert_equal value, (Settings[key.to_s] = value)
255
- assert_setting value, key
256
- end
257
- end
258
- end