jamesearl-rails-settings 1.0.2

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.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/.travis.yml ADDED
@@ -0,0 +1,9 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.3
5
+ gemfile:
6
+ - ci/Gemfile.rails-2.3.x
7
+ # - ci/Gemfile.rails-3.0.x
8
+ - ci/Gemfile.rails-3.1.x
9
+ - ci/Gemfile.rails-3.2.x
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in rails-settings.gemspec
4
+ gemspec
data/MIT-LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2006 Alex Wayne
2
+ Some additional features added 2009-2012 by Georg Ledermann
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOa AND
18
+ NONINFRINGEMENT. IN NO EVENT SaALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,151 @@
1
+ # Changes from upstream
2
+
3
+ Will attempt to use a corresponding ENV value if a setting key is not found in the database or defaults.
4
+
5
+ Example:
6
+ If you look for Setting.foo, the gem well try
7
+ Settings.all["foo"]
8
+ defaults["foo"]
9
+ ENV["FOO"]
10
+
11
+ Note the upcase.
12
+
13
+
14
+ # Settings Gem/Plugin for Rails
15
+
16
+ Settings is a gem/plugin that makes managing a table of key/value pairs easy. Think of it like a Hash stored in you database, that uses simple ActiveRecord like methods for manipulation. Keep track of any setting that you don't want to hard code into your rails app. You can store any kind of object: Strings, numbers, arrays, or any object which can be noted as YAML.
17
+
18
+
19
+ ## Requirements
20
+
21
+ Rails 2.3.x, 3.1.x or 3.2.x (due to an [issue with Rails caching](https://github.com/rails/rails/pull/2010) it does not work properly with Rails 3.0.x)
22
+
23
+ Tested with Ruby 1.8.7 and 1.9.3
24
+
25
+
26
+ ## Installation
27
+
28
+ Include the gem in your Gemfile
29
+
30
+ gem 'jamesearl-rails-settings', :require => 'rails-settings'
31
+
32
+ or install as a plugin:
33
+
34
+ ./script/plugin install git://github.com/jamesearl/rails-settings.git
35
+
36
+
37
+ You have to create the table used by the Settings model by using this migration:
38
+
39
+ class CreateSettingsTable < ActiveRecord::Migration
40
+ def self.up
41
+ create_table :settings, :force => true do |t|
42
+ t.string :var, :null => false
43
+ t.text :value
44
+ t.integer :target_id
45
+ t.string :target_type, :limit => 30
46
+ t.timestamps
47
+ end
48
+
49
+ add_index :settings, [ :target_type, :target_id, :var ], :unique => true
50
+ end
51
+
52
+ def self.down
53
+ drop_table :settings
54
+ end
55
+ end
56
+
57
+ Now update your database with:
58
+
59
+ rake db:migrate
60
+
61
+ ## Usage
62
+
63
+ The syntax is easy. First, lets create some settings to keep track of:
64
+
65
+ Settings.admin_password = 'supersecret'
66
+ Settings.date_format = '%m %d, %Y'
67
+ Settings.cocktails = ['Martini', 'Screwdriver', 'White Russian']
68
+ Settings.foo = 123
69
+ Settings.credentials = { :username => 'tom', :password => 'secret' }
70
+
71
+ Now lets read them back:
72
+
73
+ Settings.foo
74
+ # => 123
75
+
76
+ Changing an existing setting is the same as creating a new setting:
77
+
78
+ Settings.foo = 'super duper bar'
79
+
80
+ For changing an existing setting which is a Hash, you can merge new values with existing ones:
81
+
82
+ Settings.merge! :credentials, :password => 'topsecret'
83
+ Settings.credentials
84
+ # => { :username => 'tom', :password => 'topsecret' }
85
+
86
+ Decide you dont want to track a particular setting anymore?
87
+
88
+ Settings.destroy :foo
89
+ Settings.foo
90
+ # => nil
91
+
92
+ Want a list of all the settings?
93
+
94
+ Settings.all
95
+ # => { 'admin_password' => 'super_secret', 'date_format' => '%m %d, %Y' }
96
+
97
+ You need name spaces and want a list of settings for a give name space? Just choose your prefered named space delimiter and use Settings.all like this:
98
+
99
+ Settings['preferences.color'] = :blue
100
+ Settings['preferences.size'] = :large
101
+ Settings['license.key'] = 'ABC-DEF'
102
+ Settings.all('preferences.')
103
+ # => { 'preferences.color' => :blue, 'preferences.size' => :large }
104
+
105
+ Set defaults for certain settings of your app. This will cause the defined settings to return with the
106
+ Specified value even if they are not in the database. Make a new file in config/initializers/settings.rb
107
+ with the following:
108
+
109
+ Settings.defaults[:some_setting] = 'footastic'
110
+
111
+ Now even if the database is completely empty, you app will have some intelligent defaults:
112
+
113
+ Settings.some_setting
114
+ # => 'footastic'
115
+
116
+ Settings may be bound to any existing ActiveRecord object. Define this association like this:
117
+
118
+ class User < ActiveRecord::Base
119
+ has_settings
120
+ end
121
+
122
+ Then you can set/get a setting for a given user instance just by doing this:
123
+
124
+ user = User.find(123)
125
+ user.settings.color = :red
126
+ user.settings.color
127
+ # => :red
128
+
129
+ user.settings.all
130
+ # => { "color" => :red }
131
+
132
+ I you want to find users having or not having some settings, there are named scopes for this:
133
+
134
+ User.with_settings
135
+ # returns a scope of users having any setting
136
+
137
+ User.with_settings_for('color')
138
+ # returns a scope of users having a 'color' setting
139
+
140
+ User.without_settings
141
+ # returns a scope of users having no setting at all (means user.settings.all == {})
142
+
143
+ User.without_settings('color')
144
+ # returns a scope of users having no 'color' setting (means user.settings.color == nil)
145
+
146
+ For better performance, you can enable caching, e.g.:
147
+
148
+ Settings.cache = ActiveSupport::Cache::MemoryStore.new
149
+ Settings.cache_options = { :expires_in => 5.minutes }
150
+
151
+ That's all there is to it! Enjoy!
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << 'lib' << 'test'
5
+ t.test_files = Dir.glob("test/**/*_test.rb")
6
+ t.verbose = true
7
+ end
8
+
9
+ task :default => :test
10
+
11
+ require 'bundler/gem_tasks'
@@ -0,0 +1,5 @@
1
+ source :rubygems
2
+
3
+ gem 'activerecord', '~> 2.3.14'
4
+ gem 'sqlite3'
5
+ gem 'rake'
@@ -0,0 +1,5 @@
1
+ source :rubygems
2
+
3
+ gem 'activerecord', '~> 3.0.12'
4
+ gem 'sqlite3'
5
+ gem 'rake'
@@ -0,0 +1,5 @@
1
+ source :rubygems
2
+
3
+ gem 'activerecord', '~> 3.1.4'
4
+ gem 'sqlite3'
5
+ gem 'rake'
@@ -0,0 +1,5 @@
1
+ source :rubygems
2
+
3
+ gem 'activerecord', '~> 3.2.2'
4
+ gem 'sqlite3'
5
+ gem 'rake'
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'rails-settings'
@@ -0,0 +1,5 @@
1
+ require 'rails-settings/version'
2
+ require 'rails-settings/null_store'
3
+ require 'rails-settings/active_record'
4
+ require 'rails-settings/settings'
5
+ require 'rails-settings/scoped_settings'
@@ -0,0 +1,30 @@
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
+ after_destroy { |user| user.settings.target_scoped.delete_all }
9
+
10
+ scope_method = ActiveRecord::VERSION::MAJOR < 3 ? :named_scope : :scope
11
+
12
+ send scope_method, :with_settings, :joins => "JOIN settings ON (settings.target_id = #{self.table_name}.#{self.primary_key} AND
13
+ settings.target_type = '#{self.base_class.name}')",
14
+ :select => "DISTINCT #{self.table_name}.*"
15
+
16
+ send scope_method, :with_settings_for, lambda { |var| { :joins => "JOIN settings ON (settings.target_id = #{self.table_name}.#{self.primary_key} AND
17
+ settings.target_type = '#{self.base_class.name}') AND
18
+ settings.var = '#{var}'" } }
19
+
20
+ send scope_method, :without_settings, :joins => "LEFT JOIN settings ON (settings.target_id = #{self.table_name}.#{self.primary_key} AND
21
+ settings.target_type = '#{self.base_class.name}')",
22
+ :conditions => 'settings.id IS NULL'
23
+
24
+ send scope_method, :without_settings_for, lambda { |var| { :joins => "LEFT 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
+ :conditions => 'settings.id IS NULL' } }
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,48 @@
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
@@ -0,0 +1,14 @@
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.id
9
+ end
10
+
11
+ def self.target_type
12
+ @target.class.base_class.to_s
13
+ end
14
+ end
@@ -0,0 +1,136 @@
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
+ result.with_indifferent_access
72
+ end
73
+
74
+ #get a setting value by [] notation
75
+ def self.[](var_name)
76
+ cache.fetch(cache_key(var_name), cache_options) do
77
+ if (var = target(var_name)).present?
78
+ var.value
79
+ else
80
+ ENV[var_name.to_s.upcase] || defaults[var_name.to_s]
81
+ end
82
+ end
83
+ end
84
+
85
+ #set a setting value by [] notation
86
+ def self.[]=(var_name, value)
87
+ record = target_scoped.find_or_initialize_by_var(var_name.to_s)
88
+ record.value = value
89
+ record.save!
90
+ cache.write(cache_key(var_name), value, cache_options)
91
+ value
92
+ end
93
+
94
+ def self.merge!(var_name, hash_value)
95
+ raise ArgumentError unless hash_value.is_a?(Hash)
96
+
97
+ old_value = self[var_name] || {}
98
+ raise TypeError, "Existing value is not a hash, can't merge!" unless old_value.is_a?(Hash)
99
+
100
+ new_value = old_value.merge(hash_value)
101
+ self[var_name] = new_value if new_value != old_value
102
+
103
+ new_value
104
+ end
105
+
106
+ def self.target(var_name)
107
+ target_scoped.find_by_var(var_name.to_s)
108
+ end
109
+
110
+ #get the value field, YAML decoded
111
+ def value
112
+ YAML::load(self[:value])
113
+ end
114
+
115
+ #set the value field, YAML encoded
116
+ def value=(new_value)
117
+ self[:value] = new_value.to_yaml
118
+ end
119
+
120
+ def self.target_scoped
121
+ Settings.scoped_by_target_type_and_target_id(target_type, target_id)
122
+ end
123
+
124
+ #Deprecated!
125
+ def self.reload # :nodoc:
126
+ self
127
+ end
128
+
129
+ def self.target_id
130
+ nil
131
+ end
132
+
133
+ def self.target_type
134
+ nil
135
+ end
136
+ end
@@ -0,0 +1,3 @@
1
+ module RailsSettings
2
+ VERSION = '1.0.2'
3
+ end
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+ require 'rails-settings/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'jamesearl-rails-settings'
7
+ s.version = RailsSettings::VERSION
8
+ s.authors = ['James Cunningham']
9
+ s.email = ['james@einherj.ar.com']
10
+ s.homepage = 'https://github.com/jamesearl/rails-settings'
11
+ s.summary = %q{Settings management for ActiveRecord objects}
12
+ s.description = %q{Ruby Gem that makes managing a table of key/value pairs easy. Think of it like a Hash stored in you database, that uses simple ActiveRecord like methods for manipulation.}
13
+
14
+ s.rubyforge_project = 'jamesearl-rails-settings'
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ['lib']
20
+
21
+ # specify any dependencies here; for example:
22
+ # s.add_development_dependency "rspec"
23
+ # s.add_runtime_dependency "rest-client"
24
+ s.add_dependency 'activerecord', '>= 2.3'
25
+ s.add_development_dependency 'rake'
26
+ s.add_development_dependency 'sqlite3'
27
+ end
@@ -0,0 +1,213 @@
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
+ end
10
+
11
+ def teardown
12
+ User.delete_all
13
+ Settings.delete_all
14
+ end
15
+
16
+ def test_defaults
17
+ Settings.defaults[:foo] = 'default foo'
18
+
19
+ assert_nil Settings.target(:foo)
20
+ assert_equal 'default foo', Settings.foo
21
+
22
+ Settings.foo = 'bar'
23
+ assert_equal 'bar', Settings.foo
24
+ assert_not_nil Settings.target(:foo)
25
+ end
26
+
27
+ def tests_defaults_true
28
+ Settings.defaults[:foo] = true
29
+ assert_equal true, Settings.foo
30
+ end
31
+
32
+ def tests_defaults_false
33
+ Settings.defaults[:foo] = false
34
+ assert_equal false, Settings.foo
35
+ end
36
+
37
+ def test_get
38
+ assert_setting 'foo', :test
39
+ assert_setting 'bar', :test2
40
+ end
41
+
42
+ def test_update
43
+ assert_assign_setting '321', :test
44
+ end
45
+
46
+ def test_create
47
+ assert_assign_setting '123', :onetwothree
48
+ end
49
+
50
+ def test_complex_serialization
51
+ complex = [1, '2', {:three => true}]
52
+ Settings.complex = complex
53
+ assert_equal complex, Settings.complex
54
+ end
55
+
56
+ def test_serialization_of_float
57
+ Settings.float = 0.01
58
+ Settings.reload
59
+ assert_equal 0.01, Settings.float
60
+ assert_equal 0.02, Settings.float * 2
61
+ end
62
+
63
+ def test_target_scope
64
+ user1 = User.create :name => 'First user'
65
+ user2 = User.create :name => 'Second user'
66
+
67
+ assert_assign_setting 1, :one, user1
68
+ assert_assign_setting 2, :two, user2
69
+
70
+ assert_setting 1, :one, user1
71
+ assert_setting 2, :two, user2
72
+
73
+ assert_setting nil, :one
74
+ assert_setting nil, :two
75
+
76
+ assert_setting nil, :two, user1
77
+ assert_setting nil, :one, user2
78
+
79
+ assert_equal({ "one" => 1}, user1.settings.all('one'))
80
+ assert_equal({ "two" => 2}, user2.settings.all('two'))
81
+ assert_equal({ "one" => 1}, user1.settings.all('o'))
82
+ assert_equal({}, user1.settings.all('non_existing_var'))
83
+ end
84
+
85
+ def test_named_scope
86
+ user_without_settings = User.create :name => 'User without settings'
87
+ user_with_settings = User.create :name => 'User with settings'
88
+ user_with_settings.settings.one = '1'
89
+ user_with_settings.settings.two = '2'
90
+
91
+ assert_equal [user_with_settings], User.with_settings
92
+ assert_equal [user_with_settings], User.with_settings_for('one')
93
+ assert_equal [user_with_settings], User.with_settings_for('two')
94
+ assert_equal [], User.with_settings_for('foo')
95
+
96
+ assert_equal [user_without_settings], User.without_settings
97
+ assert_equal [user_without_settings], User.without_settings_for('one')
98
+ assert_equal [user_without_settings], User.without_settings_for('two')
99
+ assert_equal [user_without_settings, user_with_settings], User.without_settings_for('foo')
100
+ end
101
+
102
+ def test_delete_settings_after_destroying_target
103
+ user1 = User.create :name => 'Mr. Foo'
104
+ user2 = User.create :name => 'Mr. Bar'
105
+ user1.settings.example = 42
106
+ user2.settings.example = 43
107
+
108
+ before_count = Settings.count
109
+ user1.destroy
110
+ assert_equal before_count - 1, Settings.count
111
+
112
+ before_count = Settings.count
113
+ user2.destroy
114
+ assert_equal before_count - 1, Settings.count
115
+ end
116
+
117
+ def test_all
118
+ assert_equal({ "test2" => "bar", "test" => "foo" }, Settings.all)
119
+ assert_equal({ "test2" => "bar" }, Settings.all('test2'))
120
+ assert_equal({ "test2" => "bar", "test" => "foo" }, Settings.all('test'))
121
+ assert_equal({}, Settings.all('non_existing_var'))
122
+ end
123
+
124
+ def test_merge
125
+ assert_raise(TypeError) do
126
+ Settings.merge! :test, { :a => 1 }
127
+ end
128
+
129
+ Settings[:hash] = { :one => 1 }
130
+ Settings.merge! :hash, { :two => 2 }
131
+ assert_equal({ :one => 1, :two => 2 }, Settings[:hash])
132
+
133
+ assert_raise(ArgumentError) do
134
+ Settings.merge! :hash, 123
135
+ end
136
+
137
+ Settings.merge! :empty_hash, { :two => 2 }
138
+ assert_equal({ :two => 2 }, Settings[:empty_hash])
139
+ end
140
+
141
+ def test_destroy
142
+ Settings.destroy :test
143
+ assert_equal nil, Settings.test
144
+
145
+ assert_raise(Settings::SettingNotFound) do
146
+ Settings.destroy :unknown
147
+ end
148
+ end
149
+
150
+ def test_false
151
+ Settings.test3 = false
152
+ assert_setting(false, 'test3')
153
+
154
+ Settings.destroy :test3
155
+ assert_setting(nil, 'test3')
156
+ end
157
+
158
+ private
159
+ def assert_setting(value, key, scope_target=nil)
160
+ key = key.to_sym
161
+
162
+ if scope_target
163
+ assert_equal value, scope_target.instance_eval("settings.#{key}")
164
+ assert_equal value, scope_target.settings[key.to_sym]
165
+ assert_equal value, scope_target.settings[key.to_s]
166
+ else
167
+ assert_equal value, eval("Settings.#{key}")
168
+ assert_equal value, Settings[key.to_sym]
169
+ assert_equal value, Settings[key.to_s]
170
+ end
171
+ end
172
+
173
+ def assert_assign_setting(value, key, scope_target=nil)
174
+ key = key.to_sym
175
+
176
+ if scope_target
177
+ assert_equal value, (scope_target.settings[key] = value)
178
+ assert_setting value, key, scope_target
179
+ scope_target.settings[key] = nil
180
+
181
+ assert_equal value, (scope_target.settings[key.to_s] = value)
182
+ assert_setting value, key, scope_target
183
+ else
184
+ assert_equal value, (Settings[key] = value)
185
+ assert_setting value, key
186
+ Settings[key] = nil
187
+
188
+ assert_equal value, (Settings[key.to_s] = value)
189
+ assert_setting value, key
190
+ end
191
+ end
192
+ end
193
+
194
+ class CachedSettingsTest < SettingsTest
195
+ def setup
196
+ Settings.cache = ActiveSupport::Cache::MemoryStore.new
197
+ Settings.cache_options = { :expires_in => 5.minutes }
198
+ super
199
+ end
200
+
201
+ def test_caching_is_in_place
202
+ Settings.progress = "boing"
203
+ Settings.connection.execute("delete from settings")
204
+ assert_equal "boing", Settings.progress
205
+ Settings.cache.clear
206
+ assert_nil Settings.progress
207
+ end
208
+
209
+ def teardown
210
+ Settings.cache.clear
211
+ super
212
+ end
213
+ end
@@ -0,0 +1,34 @@
1
+ require 'rubygems'
2
+
3
+ require 'active_support'
4
+ require 'active_support/test_case'
5
+ require 'active_record'
6
+ require 'test/unit'
7
+
8
+ require "#{File.dirname(__FILE__)}/../init"
9
+
10
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
11
+ ActiveRecord::Migration.verbose = false
12
+
13
+ class User < ActiveRecord::Base
14
+ has_settings
15
+ end
16
+
17
+ def setup_db
18
+ ActiveRecord::Schema.define(:version => 1) do
19
+ create_table :settings do |t|
20
+ t.string :var, :null => false
21
+ t.text :value, :null => true
22
+ t.integer :target_id, :null => true
23
+ t.string :target_type, :limit => 30, :null => true
24
+ t.timestamps
25
+ end
26
+ add_index :settings, [ :target_type, :target_id, :var ], :unique => true
27
+
28
+ create_table :users do |t|
29
+ t.string :name
30
+ end
31
+ end
32
+ end
33
+
34
+ puts "Testing with ActiveRecord #{ActiveRecord::VERSION::STRING}"
metadata ADDED
@@ -0,0 +1,117 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jamesearl-rails-settings
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - James Cunningham
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-16 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activerecord
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '2.3'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '2.3'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: sqlite3
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: Ruby Gem that makes managing a table of key/value pairs easy. Think of
63
+ it like a Hash stored in you database, that uses simple ActiveRecord like methods
64
+ for manipulation.
65
+ email:
66
+ - james@einherj.ar.com
67
+ executables: []
68
+ extensions: []
69
+ extra_rdoc_files: []
70
+ files:
71
+ - .gitignore
72
+ - .travis.yml
73
+ - Gemfile
74
+ - MIT-LICENSE
75
+ - README.md
76
+ - Rakefile
77
+ - ci/Gemfile.rails-2.3.x
78
+ - ci/Gemfile.rails-3.0.x
79
+ - ci/Gemfile.rails-3.1.x
80
+ - ci/Gemfile.rails-3.2.x
81
+ - init.rb
82
+ - lib/rails-settings.rb
83
+ - lib/rails-settings/active_record.rb
84
+ - lib/rails-settings/null_store.rb
85
+ - lib/rails-settings/scoped_settings.rb
86
+ - lib/rails-settings/settings.rb
87
+ - lib/rails-settings/version.rb
88
+ - rails-settings.gemspec
89
+ - test/settings_test.rb
90
+ - test/test_helper.rb
91
+ homepage: https://github.com/jamesearl/rails-settings
92
+ licenses: []
93
+ post_install_message:
94
+ rdoc_options: []
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ! '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ none: false
105
+ requirements:
106
+ - - ! '>='
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ requirements: []
110
+ rubyforge_project: jamesearl-rails-settings
111
+ rubygems_version: 1.8.22
112
+ signing_key:
113
+ specification_version: 3
114
+ summary: Settings management for ActiveRecord objects
115
+ test_files:
116
+ - test/settings_test.rb
117
+ - test/test_helper.rb