kvc 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,10 @@
1
+ === 0.1.0 / 2009-12-10
2
+
3
+ * 1 enhancement
4
+
5
+ * Reload database records by default.
6
+
7
+
1
8
  === 0.0.3 / 2009-06-27
2
9
 
3
10
  * 1 minor enhancement
@@ -61,14 +61,12 @@ If need be, validate specific key values in an initializer:
61
61
 
62
62
  Install:
63
63
 
64
- % gem install stephencelis-kvc --source=http://gems.github.com
64
+ % gem install kvc
65
65
 
66
66
 
67
67
  And configure:
68
68
 
69
- config.gem "stephencelis-kvc",
70
- :lib => "kvc",
71
- :source => "http://gems.github.com"
69
+ config.gem "kvc"
72
70
 
73
71
 
74
72
  === As a plugin
@@ -98,11 +96,11 @@ the table at any time, execute the "kvc:drop_table" Rake task).
98
96
 
99
97
  (c) 2009-* Stephen Celis, stephen@stephencelis.com.
100
98
 
101
- Permission is hereby granted, free of charge, to any person obtaining a copy
102
- of this software and associated documentation files (the "Software"), to deal
103
- in the Software without restriction, including without limitation the rights
104
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
105
- copies of the Software, and to permit persons to whom the Software is
99
+ Permission is hereby granted, free of charge, to any person obtaining a copy
100
+ of this software and associated documentation files (the "Software"), to deal
101
+ in the Software without restriction, including without limitation the rights
102
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
103
+ copies of the Software, and to permit persons to whom the Software is
106
104
  furnished to do so, subject to the following conditions:
107
105
 
108
106
  The above copyright notice and this permission notice shall be included in all
data/Rakefile CHANGED
@@ -1,14 +1,8 @@
1
1
  $: << File.dirname(__FILE__) + "/lib"
2
2
  require "rubygems"
3
- require "hoe"
4
3
  require "active_record"
5
4
  require "kvc"
6
5
 
7
- Hoe.new("kvc", KVC::VERSION) do |p|
8
- p.developer("Stephen Celis", "stephen@stephencelis.com")
9
- p.remote_rdoc_dir = ''
10
- end
11
-
12
6
  require 'rake'
13
7
  require 'rake/testtask'
14
8
  require 'rake/rdoctask'
data/lib/kvc.rb CHANGED
@@ -18,7 +18,7 @@
18
18
  # Or get creative:
19
19
  #
20
20
  # KVC["Chad's expensive guitar"] = Fender::Stratocaster.new(1957)
21
- #
21
+ #
22
22
  # By default, nonexistent keys return +nil+ values, but you can be stricter if
23
23
  # you want to avoid typo-based bugs:
24
24
  #
@@ -35,7 +35,7 @@
35
35
  #
36
36
  # Failed validations will raise <tt>ActiveRecord::RecordInvalid</tt>.
37
37
  module KVC
38
- VERSION = "0.0.3"
38
+ VERSION = "0.1.0"
39
39
 
40
40
  class << self
41
41
  def [](key)
@@ -65,3 +65,7 @@ module KVC
65
65
  end
66
66
  end
67
67
  end
68
+
69
+ def KVC(key)
70
+ KVC[key]
71
+ end
@@ -13,10 +13,16 @@ class KVC::Settings < ActiveRecord::Base
13
13
  @@strict_keys = false
14
14
  cattr_accessor :strict_keys
15
15
 
16
+ # Reload serialized <tt>ActiveRecord::Base</tt> records.
17
+ @@reload_records = true
18
+ cattr_accessor :reload_records
19
+
16
20
  @@validations = HashWithIndifferentAccess.new []
17
21
  cattr_reader :validations
22
+
18
23
  class << self
19
- alias strict_keys? strict_keys
24
+ alias strict_keys? strict_keys
25
+ alias reload_records? reload_records
20
26
 
21
27
  # Config takes a block for configuration. For now, this provides
22
28
  # rudimentary validation. E.g.:
@@ -33,6 +39,23 @@ class KVC::Settings < ActiveRecord::Base
33
39
  self
34
40
  end.instance_eval(&block)
35
41
  end
42
+
43
+ # Recursively reload saved records. To short-circuit record reloading, set
44
+ # <tt>KVC::Settings.reload_records = false</tt>.
45
+ def deserialize(object)
46
+ return object unless reload_records?
47
+
48
+ case object
49
+ when ActiveRecord::Base
50
+ object.new_record? ? object : object.reload
51
+ when Array
52
+ object.map { |o| deserialize(o) }
53
+ when Hash
54
+ object.each { |k, v| object[k] = deserialize(v) }
55
+ else
56
+ object
57
+ end
58
+ end
36
59
  end
37
60
 
38
61
  # Active Record does not automatically namespace tables.
@@ -43,7 +66,7 @@ class KVC::Settings < ActiveRecord::Base
43
66
 
44
67
  # Deserializes value from database.
45
68
  def value
46
- @value ||= YAML.load read_attribute(:value)
69
+ @value ||= KVC::Settings.deserialize YAML.load(read_attribute(:value))
47
70
  end
48
71
 
49
72
  # Serializes value for database.
@@ -7,6 +7,8 @@
7
7
  class KVC::SettingsProxy
8
8
  undef_method *instance_methods.grep(/^(?!__|nil\?|send)/)
9
9
 
10
+ attr_reader :setting
11
+
10
12
  def initialize(setting)
11
13
  @setting = setting
12
14
  end
@@ -14,11 +16,13 @@ class KVC::SettingsProxy
14
16
  private
15
17
 
16
18
  def method_missing(method, *args, &block)
17
- return @setting.send(method) if [:created_at, :updated_at].include? method
19
+ return setting.send(method) if [:created_at, :updated_at].include? method
20
+
21
+ return_value = setting.value.send(method, *args, &block)
22
+ stored_value = KVC::Settings.deserialize YAML.load(setting[:value])
18
23
 
19
- return_value = @setting.value.send(method, *args, &block)
20
- if @setting.value != YAML.load(@setting.read_attribute(:value))
21
- @setting.update_attribute :value, @setting.value
24
+ if setting.value != stored_value
25
+ setting.update_attribute :value, setting.value
22
26
  return self # Allow for chaining.
23
27
  end
24
28
 
@@ -3,12 +3,25 @@ require 'rubygems'
3
3
  require 'active_record'
4
4
  require 'active_support'
5
5
  require 'active_support/test_case'
6
+ ActiveRecord::Migration.verbose = false
6
7
 
7
8
  $: << File.expand_path(File.dirname(__FILE__) + "/../lib") <<
8
9
  File.expand_path(File.dirname(__FILE__) + "/../app/models")
9
10
 
10
11
  ActiveRecord::Base.establish_connection :adapter => 'sqlite3',
11
- :dbfile => ':memory:'
12
+ :database => ':memory:'
13
+
14
+ ActiveRecord::Schema.define(:version => 1) do
15
+ create_table :guitars do |t|
16
+ t.string :make, :model
17
+ t.timestamps
18
+ end
19
+
20
+ create_table :keyboards do |t|
21
+ t.string :make, :model
22
+ t.timestamps
23
+ end
24
+ end
12
25
 
13
26
  require "kvc"
14
27
  require "kvc/settings"
@@ -16,6 +29,13 @@ require "kvc/settings_proxy"
16
29
 
17
30
  logger = Logger.new(STDOUT)
18
31
 
32
+ class Guitar < ActiveRecord::Base
33
+ end
34
+
35
+ class Keyboard < ActiveRecord::Base
36
+ validates_presence_of :make
37
+ end
38
+
19
39
  class KVCTest < ActiveSupport::TestCase
20
40
  teardown do
21
41
  KVC::Settings.destroy_all
@@ -80,6 +100,55 @@ class KVCTest < ActiveSupport::TestCase
80
100
  assert_kind_of Integer, KVC.favorite_year
81
101
  end
82
102
 
103
+ test "models should serialize and deserialize updated versions" do
104
+ instruments = {
105
+ :guitars => {
106
+ :favorites => [
107
+ Guitar.create(:make => "Gibson", :model => "Melody Maker"),
108
+ Guitar.create(:make => "Epiphone", :model => "Les Paul"),
109
+ ],
110
+ :not_so_good => [
111
+ Guitar.create(:make => "Samick")
112
+ ]
113
+ },
114
+ :keyboard => Keyboard.create(:make => "Yamaha")
115
+ }
116
+
117
+ KVC.instruments = Marshal.load Marshal.dump(instruments) # Deep copy.
118
+ instruments[:keyboard].update_attribute(:model, "Privia PX-130")
119
+
120
+ assert_equal instruments, KVC.instruments
121
+ assert_equal instruments[:keyboard].model, KVC.instruments[:keyboard].model
122
+ end
123
+
124
+ test "should not reload records if record reloading is off" do
125
+ begin
126
+ KVC::Settings.reload_records = false
127
+ KVC.guitar = Guitar.create(:make => "Yamaha")
128
+ guitar = Guitar.last
129
+ guitar.update_attribute :make, "Yamahahaha"
130
+ assert_not_equal guitar.make, KVC.guitar.make
131
+ ensure
132
+ KVC::Settings.reload_records = true
133
+ end
134
+ end
135
+
136
+ test "unsaved models should deserialize" do
137
+ keyboard = Keyboard.new :model => "Some kind of synthesizer."
138
+ assert_nil keyboard.id
139
+ KVC["Which make was it again?"] = keyboard.clone # Unsaved copy.
140
+ assert_equal keyboard, KVC["Which make was it again?"]
141
+ end
142
+
143
+ test "missing models should raise exceptions" do
144
+ guitar = Guitar.create
145
+ KVC.ghost_guitar = guitar
146
+ guitar.destroy
147
+ assert_raise ActiveRecord::RecordNotFound do
148
+ KVC.ghost_guitar.touch
149
+ end
150
+ end
151
+
83
152
  test "can set attributes with whitespace and symbols" do
84
153
  assert KVC["uses_git?"] = true
85
154
  assert KVC.uses_git?
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kvc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen Celis
@@ -9,19 +9,10 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-06-27 00:00:00 -05:00
12
+ date: 2009-12-10 00:00:00 -06:00
13
13
  default_executable:
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
16
- name: hoe
17
- type: :development
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
20
- requirements:
21
- - - ">="
22
- - !ruby/object:Gem::Version
23
- version: 2.0.0
24
- version:
14
+ dependencies: []
15
+
25
16
  description: |-
26
17
  KVC (Key-Value Configuration) provides a powerful, transparent way to maintain
27
18
  mutable app settings in the database.
@@ -32,13 +23,13 @@ executables: []
32
23
  extensions: []
33
24
 
34
25
  extra_rdoc_files:
35
- - History.txt
26
+ - History.rdoc
36
27
  - Manifest.txt
37
- - README.txt
28
+ - README.rdoc
38
29
  files:
39
- - History.txt
30
+ - History.rdoc
40
31
  - Manifest.txt
41
- - README.txt
32
+ - README.rdoc
42
33
  - Rakefile
43
34
  - lib/kvc.rb
44
35
  - lib/kvc/settings.rb
@@ -53,7 +44,7 @@ licenses: []
53
44
  post_install_message:
54
45
  rdoc_options:
55
46
  - --main
56
- - README.txt
47
+ - README.rdoc
57
48
  require_paths:
58
49
  - lib
59
50
  required_ruby_version: !ruby/object:Gem::Requirement