store_configurable 3.2.4 → 3.2.5
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/CHANGELOG +5 -0
- data/README.md +11 -2
- data/lib/store_configurable/read.rb +7 -1
- data/lib/store_configurable/version.rb +1 -1
- data/test/cases/base_test.rb +15 -2
- data/test/helper.rb +12 -1
- data/test/support/activerecord.rb +51 -0
- metadata +34 -11
data/CHANGELOG
CHANGED
data/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
# StoreConfigurable
|
|
3
3
|
|
|
4
|
-
A zero-configuration recursive Hash for storing a tree of options in a serialized ActiveRecord column. Includes self aware hooks that delegate dirty/changed state to your configs owner.
|
|
4
|
+
A zero-configuration recursive Hash for storing a tree of options in a serialized ActiveRecord column. Includes self aware hooks that delegate dirty/changed state to your configs owner. Read my article [*A Lesson In Recursion In Ruby*](http://metaskills.net/2012/03/12/store-configurable-a-lesson-in-recursion-in-ruby/) if you are interested in how this library works.
|
|
5
5
|
|
|
6
6
|
<img src="http://cdn.actionmoniker.com/share/recursive_kitty_small.jpg" alt="Recursive Github Kitty" width="260" height="160" style="float:right; margin:-20px 35px 15px 15px; background-color:#fff; padding:13px; -moz-box-shadow: 5px 5px 5px rgba(0,0,0,0.5); -webkit-box-shadow: 5px 5px 5px rgba(0,0,0,0.5); box-shadow: 5px 5px 5px rgba(0,0,0,0.5); -moz-transform: rotate(-2deg); -webkit-transform: rotate(-2deg); transform: rotate(-2deg);">
|
|
7
7
|
|
|
@@ -18,7 +18,7 @@ gem 'store_configurable', '~> 3.2.0'
|
|
|
18
18
|
|
|
19
19
|
## Setup
|
|
20
20
|
|
|
21
|
-
To use StoreConfigurable, you must create
|
|
21
|
+
To use StoreConfigurable, you must create a `_config` column in the model's table. Make sure that you declare this column as a text type, so there's plenty of room.
|
|
22
22
|
|
|
23
23
|
```ruby
|
|
24
24
|
class AddStoreConfigurableField < ActiveRecord::Migration
|
|
@@ -115,6 +115,15 @@ StoreConfigurable persists your configuration data in YAML format to the `_confi
|
|
|
115
115
|
- :this: deep_value
|
|
116
116
|
```
|
|
117
117
|
|
|
118
|
+
## Todo
|
|
119
|
+
|
|
120
|
+
* Incorporate an option to compress serialized data. Gzip, [MessagePack](http://msgpack.org/), Etc...
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
## Other Solutions
|
|
124
|
+
|
|
125
|
+
* [StoreField](https://github.com/kenn/store_field) - Similar approach but no dirty tracking and still requires manual key configs.
|
|
126
|
+
|
|
118
127
|
|
|
119
128
|
## License
|
|
120
129
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module StoreConfigurable
|
|
2
2
|
module Read
|
|
3
|
-
|
|
3
|
+
|
|
4
4
|
# Our main syntatic interface to the underlying +_config+ store. This method ensures that
|
|
5
5
|
# +self+, the store's owner, will allways be set in the config object. Hence allowing all
|
|
6
6
|
# other recursive options to get a handle back to the owner.
|
|
@@ -55,6 +55,12 @@ module StoreConfigurable
|
|
|
55
55
|
config
|
|
56
56
|
super
|
|
57
57
|
end
|
|
58
|
+
|
|
59
|
+
# We never want the `_config` key in the list of attributes. This keeps practically keeps
|
|
60
|
+
# ActiveRecord from always saving this serialized column too
|
|
61
|
+
def attributes
|
|
62
|
+
super.tap { |x| x.delete('_config') }
|
|
63
|
+
end
|
|
58
64
|
|
|
59
65
|
end
|
|
60
66
|
end
|
data/test/cases/base_test.rb
CHANGED
|
@@ -46,7 +46,7 @@ class StoreConfigurable::BaseTest < StoreConfigurable::TestCase
|
|
|
46
46
|
user_ken.config[:sortable_tables][:column].must_equal 'updated_at'
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
-
it 'must
|
|
49
|
+
it 'must mark owner as dirty after missing getter since that inits a new namespace' do
|
|
50
50
|
user_ken.config.bar
|
|
51
51
|
user_ken.must_be :config_changed?
|
|
52
52
|
end
|
|
@@ -78,9 +78,22 @@ class StoreConfigurable::BaseTest < StoreConfigurable::TestCase
|
|
|
78
78
|
user_ken.save!
|
|
79
79
|
@user = User.find(user_ken.id)
|
|
80
80
|
end
|
|
81
|
-
|
|
81
|
+
|
|
82
82
|
it 'wont be dirty after loading' do
|
|
83
83
|
@user.wont_be :config_changed?
|
|
84
|
+
@user.wont_be :changed?
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it 'does not update the _config column when not dirty, bypassing ActiveRecords always save serialized columns' do
|
|
88
|
+
assert_queries(0) { @user.save! }
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it 'allows the dirty _config value to be persisted' do
|
|
92
|
+
new_color = '#f1f1f1'
|
|
93
|
+
@user.config.color = new_color
|
|
94
|
+
@user.must_be :changed?
|
|
95
|
+
assert_queries(1) { @user.save! }
|
|
96
|
+
User.find(@user.id).config.color.must_equal new_color
|
|
84
97
|
end
|
|
85
98
|
|
|
86
99
|
it 'can reconsitute saved values' do
|
data/test/helper.rb
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
require 'rubygems'
|
|
2
2
|
require 'bundler'
|
|
3
|
-
require
|
|
3
|
+
require 'bundler/setup'
|
|
4
4
|
Bundler.require
|
|
5
5
|
require 'store_configurable'
|
|
6
6
|
require 'active_record/base'
|
|
7
|
+
require 'support/activerecord'
|
|
7
8
|
require 'minitest/autorun'
|
|
8
9
|
require 'logger'
|
|
9
10
|
|
|
@@ -14,11 +15,14 @@ ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => ':me
|
|
|
14
15
|
|
|
15
16
|
module StoreConfigurable
|
|
16
17
|
class TestCase < MiniTest::Spec
|
|
18
|
+
|
|
19
|
+
include ActiveRecordTestHelper
|
|
17
20
|
|
|
18
21
|
before { setup_environment }
|
|
19
22
|
|
|
20
23
|
let(:new_user) { User.new }
|
|
21
24
|
let(:user_ken) { User.find_by_email('ken@metaskills.net') }
|
|
25
|
+
let(:post_sc) { Post.find_by_title('StoreConfigurable') }
|
|
22
26
|
|
|
23
27
|
def setup_environment
|
|
24
28
|
setup_database
|
|
@@ -34,12 +38,16 @@ module StoreConfigurable
|
|
|
34
38
|
t.string :name, :email
|
|
35
39
|
t.text :_config
|
|
36
40
|
end
|
|
41
|
+
connection.create_table :posts, :force => true do |t|
|
|
42
|
+
t.string :title, :body
|
|
43
|
+
end
|
|
37
44
|
end
|
|
38
45
|
end
|
|
39
46
|
end
|
|
40
47
|
|
|
41
48
|
def setup_data
|
|
42
49
|
User.create :name => 'Ken Collins', :email => 'ken@metaskills.net'
|
|
50
|
+
Post.create :title => 'StoreConfigurable', :body => 'test'
|
|
43
51
|
end
|
|
44
52
|
|
|
45
53
|
end
|
|
@@ -54,3 +62,6 @@ end
|
|
|
54
62
|
class User < ActiveRecord::Base
|
|
55
63
|
store_configurable
|
|
56
64
|
end
|
|
65
|
+
|
|
66
|
+
class Post < ActiveRecord::Base
|
|
67
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module StoreConfigurable
|
|
2
|
+
module ActiveRecordTestHelper
|
|
3
|
+
|
|
4
|
+
protected
|
|
5
|
+
|
|
6
|
+
class SQLCounter
|
|
7
|
+
|
|
8
|
+
class << self
|
|
9
|
+
attr_accessor :ignored_sql, :log
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
self.log = []
|
|
13
|
+
self.ignored_sql = [/^PRAGMA (?!(table_info))/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/, /^SAVEPOINT/, /^ROLLBACK TO SAVEPOINT/, /^RELEASE SAVEPOINT/, /^SHOW max_identifier_length/, /^BEGIN/i, /^COMMIT/i]
|
|
14
|
+
|
|
15
|
+
attr_reader :ignore
|
|
16
|
+
|
|
17
|
+
def initialize(ignore = Regexp.union(self.class.ignored_sql))
|
|
18
|
+
@ignore = ignore
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def call(name, start, finish, message_id, values)
|
|
22
|
+
sql = values[:sql]
|
|
23
|
+
return if 'CACHE' == values[:name] || ignore =~ sql
|
|
24
|
+
self.class.log << sql
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def assert_sql(*patterns_to_match)
|
|
30
|
+
SQLCounter.log = []
|
|
31
|
+
yield
|
|
32
|
+
SQLCounter.log
|
|
33
|
+
ensure
|
|
34
|
+
failed_patterns = []
|
|
35
|
+
patterns_to_match.each do |pattern|
|
|
36
|
+
failed_patterns << pattern unless SQLCounter.log.any?{ |sql| pattern === sql }
|
|
37
|
+
end
|
|
38
|
+
assert failed_patterns.empty?, "Query pattern(s) #{failed_patterns.map{ |p| p.inspect }.join(', ')} not found.#{SQLCounter.log.size == 0 ? '' : "\nQueries:\n#{SQLCounter.log.join("\n")}"}"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def assert_queries(num = 1)
|
|
42
|
+
SQLCounter.log = []
|
|
43
|
+
yield
|
|
44
|
+
ensure
|
|
45
|
+
assert_equal num, SQLCounter.log.size, "#{SQLCounter.log.size} instead of #{num} queries were executed.#{SQLCounter.log.size == 0 ? '' : "\nQueries:\n#{SQLCounter.log.join("\n")}"}"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
ActiveSupport::Notifications.subscribe 'sql.active_record', SQLCounter.new
|
|
49
|
+
|
|
50
|
+
end
|
|
51
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: store_configurable
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.2.
|
|
4
|
+
version: 3.2.5
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -9,11 +9,11 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2012-
|
|
12
|
+
date: 2012-09-25 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: activerecord
|
|
16
|
-
requirement:
|
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
|
17
17
|
none: false
|
|
18
18
|
requirements:
|
|
19
19
|
- - ~>
|
|
@@ -21,10 +21,15 @@ dependencies:
|
|
|
21
21
|
version: 3.2.0
|
|
22
22
|
type: :runtime
|
|
23
23
|
prerelease: false
|
|
24
|
-
version_requirements:
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
none: false
|
|
26
|
+
requirements:
|
|
27
|
+
- - ~>
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
version: 3.2.0
|
|
25
30
|
- !ruby/object:Gem::Dependency
|
|
26
31
|
name: sqlite3
|
|
27
|
-
requirement:
|
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
|
28
33
|
none: false
|
|
29
34
|
requirements:
|
|
30
35
|
- - ~>
|
|
@@ -32,10 +37,15 @@ dependencies:
|
|
|
32
37
|
version: '1.3'
|
|
33
38
|
type: :development
|
|
34
39
|
prerelease: false
|
|
35
|
-
version_requirements:
|
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
41
|
+
none: false
|
|
42
|
+
requirements:
|
|
43
|
+
- - ~>
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: '1.3'
|
|
36
46
|
- !ruby/object:Gem::Dependency
|
|
37
47
|
name: rake
|
|
38
|
-
requirement:
|
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
|
39
49
|
none: false
|
|
40
50
|
requirements:
|
|
41
51
|
- - ~>
|
|
@@ -43,10 +53,15 @@ dependencies:
|
|
|
43
53
|
version: 0.9.2
|
|
44
54
|
type: :development
|
|
45
55
|
prerelease: false
|
|
46
|
-
version_requirements:
|
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
57
|
+
none: false
|
|
58
|
+
requirements:
|
|
59
|
+
- - ~>
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: 0.9.2
|
|
47
62
|
- !ruby/object:Gem::Dependency
|
|
48
63
|
name: minitest
|
|
49
|
-
requirement:
|
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
|
50
65
|
none: false
|
|
51
66
|
requirements:
|
|
52
67
|
- - ~>
|
|
@@ -54,7 +69,12 @@ dependencies:
|
|
|
54
69
|
version: 2.8.1
|
|
55
70
|
type: :development
|
|
56
71
|
prerelease: false
|
|
57
|
-
version_requirements:
|
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
73
|
+
none: false
|
|
74
|
+
requirements:
|
|
75
|
+
- - ~>
|
|
76
|
+
- !ruby/object:Gem::Version
|
|
77
|
+
version: 2.8.1
|
|
58
78
|
description: Grown up ActiveRecord::Store config options!
|
|
59
79
|
email:
|
|
60
80
|
- ken@metaskills.net
|
|
@@ -78,6 +98,7 @@ files:
|
|
|
78
98
|
- lib/store_configurable/version.rb
|
|
79
99
|
- test/cases/base_test.rb
|
|
80
100
|
- test/helper.rb
|
|
101
|
+
- test/support/activerecord.rb
|
|
81
102
|
homepage: http://github.com/metaskills/store_configurable/
|
|
82
103
|
licenses: []
|
|
83
104
|
post_install_message:
|
|
@@ -99,7 +120,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
99
120
|
version: '0'
|
|
100
121
|
requirements: []
|
|
101
122
|
rubyforge_project:
|
|
102
|
-
rubygems_version: 1.8.
|
|
123
|
+
rubygems_version: 1.8.23
|
|
103
124
|
signing_key:
|
|
104
125
|
specification_version: 3
|
|
105
126
|
summary: A zero-configuration recursive Hash for storing a tree of options in a serialized
|
|
@@ -107,3 +128,5 @@ summary: A zero-configuration recursive Hash for storing a tree of options in a
|
|
|
107
128
|
test_files:
|
|
108
129
|
- test/cases/base_test.rb
|
|
109
130
|
- test/helper.rb
|
|
131
|
+
- test/support/activerecord.rb
|
|
132
|
+
has_rdoc:
|