ledermann-rails-settings 1.2.1 → 2.0.0

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