eatenbyagrue-entity_storage 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,8 @@
1
+ === 1.0.1 2009-09-20
2
+ * documentation update
3
+
4
+ === 1.0.0 2009-09-19
5
+
6
+ * 1 major enhancement:
7
+ * Initial release
8
+
data/Manifest.txt ADDED
@@ -0,0 +1,11 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.rdoc
4
+ Rakefile
5
+ lib/entity_storage.rb
6
+ script/console
7
+ script/destroy
8
+ script/generate
9
+ config/database.yml
10
+ test/test_entity_storage.rb
11
+ test/test_helper.rb
data/README.rdoc ADDED
@@ -0,0 +1,80 @@
1
+ = entity_storage
2
+
3
+ http://github.com/eatenbyagrue/entity_storage
4
+
5
+ == DESCRIPTION:
6
+
7
+ An easy to use, persistent Key/Value store for any Ruby on Rails project. Designed to store config values & application wide state that need to survive server restarts.
8
+
9
+ Additionally, allows users to set a list of default keys that auto-initiliazes baseline key/value pairs in the database for easy initialization.
10
+
11
+ == SYNOPSIS:
12
+
13
+ You can use the entity store like so:
14
+
15
+ # Get key value. If it doesn't exist and is specified in default list, will be initialized and returned. If not in default list, will return nil.
16
+ e = EntityStore["testkey"]
17
+ e = EntityStore.testkey
18
+ e = EntityStore[:testkey]
19
+
20
+ # sets key named 'happened' to a Time object of now
21
+ EntityStore[:happened] = Time.now
22
+ EntityStore["happened"] = Time.now
23
+ EntityStore.happened = Time.now
24
+
25
+ # find out it's default, even if it's been changed
26
+ e = EntityStore.default(:testkey)
27
+
28
+ # set it back to default
29
+ EntityStore.default!(:testkey)
30
+
31
+ # delete an item
32
+ EntityStore.delete(key)
33
+
34
+ All EntityStorage operations sync immediately with the database, so a server shutdown will not impact stored values.
35
+
36
+ Keys can be up to 512 characters in length. Values can be practically any size, and consist of any object. Objects are marshalled back and forth between database.
37
+
38
+ == REQUIREMENTS:
39
+
40
+ Requires ActiveRecord 2.2.3 or above (probably works with earlier versions, but has not been tested.)
41
+
42
+ == INSTALL:
43
+
44
+ sudo gem install entity_storage
45
+
46
+ Put the following at the bottom of your environment.rb file, or in an initializer.
47
+
48
+ require 'entity_storage'
49
+ DEFAULT_KEYS = { "testkey" => DateTime.parse("1-1-900"), "also test" => 2, "long ass key that I probably wouldn't use" => false }
50
+ EntityStore = EntityStorage::Storage.new(DEFAULT_KEYS)
51
+
52
+ On initialization, if the table "entity_storage" doesn't exist, it will be created. If you already have a table with that name, it must be in the correct format (previously created by this gem.)
53
+
54
+ You can pass a hash full of default key/value pairs. If the application accesses one of the keys, and it doesn't already exist, it will initiliaze that key with the default value. Good for getting your app to an intial starting state.
55
+
56
+
57
+ == LICENSE:
58
+
59
+ (The MIT License)
60
+
61
+ Copyright (c) 2009 Joshua Siler
62
+
63
+ Permission is hereby granted, free of charge, to any person obtaining
64
+ a copy of this software and associated documentation files (the
65
+ 'Software'), to deal in the Software without restriction, including
66
+ without limitation the rights to use, copy, modify, merge, publish,
67
+ distribute, sublicense, and/or sell copies of the Software, and to
68
+ permit persons to whom the Software is furnished to do so, subject to
69
+ the following conditions:
70
+
71
+ The above copyright notice and this permission notice shall be
72
+ included in all copies or substantial portions of the Software.
73
+
74
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
75
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
76
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
77
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
78
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
79
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
80
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,26 @@
1
+ require 'rubygems'
2
+ gem 'hoe', '>= 2.1.0'
3
+ require 'hoe'
4
+ require 'fileutils'
5
+ require './lib/entity_storage'
6
+
7
+ Hoe.plugin :newgem
8
+ # Hoe.plugin :website
9
+ # Hoe.plugin :cucumberfeatures
10
+
11
+ # Generate all the Rake tasks
12
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
13
+ $hoe = Hoe.spec 'entity_storage' do
14
+ self.developer 'Joshua Siler', 'joshua.siler@gmail.com'
15
+ # self.post_install_message = 'PostInstall.txt' # TODO remove if post-install message not required
16
+ self.rubyforge_name = self.name # TODO this is default value
17
+ self.extra_deps = [['activerecord','>= 2.2.2']]
18
+
19
+ end
20
+
21
+ require 'newgem/tasks'
22
+ Dir['tasks/**/*.rake'].each { |t| load t }
23
+
24
+ # TODO - want other tests/tasks run by default? Add them to the list
25
+ # remove_task :default
26
+ # task :default => [:spec, :features]
@@ -0,0 +1,8 @@
1
+
2
+ adapter: mysql
3
+ database:
4
+ username: root
5
+ password:
6
+ host: localhost
7
+
8
+
@@ -0,0 +1,149 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require 'rubygems'
5
+ require 'activerecord'
6
+
7
+ module EntityStorage
8
+ VERSION = '1.0.1'
9
+
10
+ class Storage
11
+ attr_accessor :defaults
12
+
13
+ # Checks for the existence of the necessary Entities table... if not here, creates it.
14
+ def initialize(defaults={})
15
+ table_exists = false
16
+ ActiveRecord::Base.connection.execute("show tables like 'entity_storage'").each { |w| table_exists = true }
17
+ unless table_exists
18
+ AddEntitiesTable.up
19
+ end
20
+
21
+ self.defaults = defaults
22
+ end
23
+
24
+ # Read a value.
25
+ def [](index)
26
+ Entity.get_value(index,defaults[index])
27
+ end
28
+
29
+ # Write a value.
30
+ def []=(index,value)
31
+ Entity.set_value(index,value)
32
+ end
33
+
34
+ # Deletes a key and associated data from store.
35
+ def delete(index)
36
+ Entity.remove_item(index)
37
+ end
38
+
39
+ # Returns the default value of a key contained in DEFAULT_KEYS global constant.
40
+ # Does not change the stored value. Use default! to reset the value.
41
+ def default(index)
42
+ self.defaults[:index]
43
+ end
44
+
45
+ # Resets the default value of a key contained in DEFAULT_KEYS global constant and returns the value.
46
+ def default!(index)
47
+ Entity.reset_value(index,defaults[index])
48
+ end
49
+
50
+ # Allows EntityStorage[:whatever] to be accessed via EntityStorage.whatever.
51
+ def method_missing(*args)
52
+ if args.length == 1
53
+ self[args[0]]
54
+ elsif args.length == 2 and args[0].to_s =~ /^(.*)=$/
55
+ self[$1.intern] = args[1]
56
+ else
57
+ super
58
+ end
59
+ end
60
+ end
61
+
62
+ # This migration is required for EntityStorage to work correctly
63
+ class AddEntitiesTable < ActiveRecord::Migration
64
+ def self.up
65
+ create_table "entity_storage", :force => true do |t|
66
+ t.string "key", :limit => 512, :null => false
67
+ t.text "value"
68
+ t.datetime "created_at"
69
+ t.datetime "updated_at"
70
+ end
71
+
72
+ add_index "entity_storage", ["created_at"], :name => "created_at"
73
+ add_index "entity_storage", ["key"], :name => "key"
74
+ add_index "entity_storage", ["updated_at"], :name => "updated_at"
75
+ end
76
+
77
+ def self.down
78
+ drop_table :entities
79
+ end
80
+ end
81
+
82
+
83
+ class Entity < ActiveRecord::Base
84
+ set_table_name "entity_storage"
85
+
86
+ # Entities should be used via class methods and not instantiated directly.
87
+ private_class_method :new
88
+
89
+ # Gets value based on specific key.
90
+ # If not found, will initialize according to defaults set in DEFAULT_KEYS global constant.
91
+ def self.get_value(search_key,default_value)
92
+ e = Entity.find_by_key(search_key.to_s)
93
+ if e.nil?
94
+ e = initialize_value(search_key,default_value)
95
+ end
96
+ e.value rescue nil
97
+ end
98
+
99
+ # Sets value for a specific key. If key doesn't exist, creates with value.
100
+ def self.set_value(search_key, new_value)
101
+ e = Entity.find_by_key(search_key.to_s)
102
+ if e.nil?
103
+ e = new
104
+ end
105
+ e.key = search_key
106
+ e.value = new_value
107
+ e.save
108
+ end
109
+
110
+ # Resets a key contained in DEFAULT_KEYS global constant to it's default value
111
+ def self.reset_value(search_key,default_value)
112
+ Entity.remove_item(search_key)
113
+ initialize_value(search_key,default_value).value
114
+ end
115
+
116
+ # Deletes a record from key store.
117
+ def self.remove_item(search_key)
118
+ e = Entity.find_by_key(search_key.to_s)
119
+ e.destroy rescue 0
120
+ end
121
+
122
+ def value=(data)
123
+ write_attribute(:value,Marshal.dump(data))
124
+ end
125
+
126
+ def value
127
+ Marshal.load(read_attribute(:value))
128
+ end
129
+
130
+ def key=(newkey)
131
+ write_attribute(:key,newkey.to_s)
132
+ end
133
+
134
+ private
135
+
136
+ # Checks provided key against internal defaults list and initializes to default value.
137
+ # Defaults defined in DEFAULT_KEYS global constant.
138
+ def self.initialize_value(search_key,default_value)
139
+ en = new
140
+ en.key = search_key
141
+ en.value = default_value
142
+ en.save
143
+ en
144
+ end
145
+
146
+ end
147
+
148
+ end
149
+
data/script/console ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
+ # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/entity_storage.rb'}"
9
+ puts "Loading entity_storage gem"
10
+ exec "#{irb} #{libs} --simple-prompt"
data/script/destroy ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
data/script/generate ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
@@ -0,0 +1,90 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestEntityStorage < Test::Unit::TestCase
4
+ DEFAULT_KEYS = { "test" => DateTime.parse("1-1-900"), "also test" => 2, "long ass key that I probably wouldn't use" => false }
5
+ attr_accessor :entity_storage
6
+
7
+ def setup
8
+ ActiveRecord::Base.establish_connection(YAML::load(File.read(File.dirname(__FILE__) + '/../config/database.yml'))) unless ActiveRecord::Base.connected?
9
+ self.entity_storage ||= EntityStorage::Storage.new(DEFAULT_KEYS)
10
+ end
11
+
12
+ # tests value setting and getting functionality, along with default creation
13
+ def test_defaultkeys
14
+ DEFAULT_KEYS.each { |key,value|
15
+ self.entity_storage.delete(key)
16
+
17
+ # set key when it doesn't exist, should go to default
18
+ e = self.entity_storage[key]
19
+ assert_equal e, value
20
+
21
+ # set and try method missing access
22
+ if key[/\w/] == key
23
+ eval("e = self.entity_storage."+key)
24
+ assert_equal e, value
25
+ end
26
+
27
+ # change it to something else
28
+ self.entity_storage[key] = Time.now.to_s
29
+ e = self.entity_storage[key]
30
+ assert_not_equal e, value
31
+
32
+ # find out it's default
33
+ e = self.entity_storage.default(key)
34
+ assert_not_equal e, value
35
+
36
+ # set it back to default
37
+ self.entity_storage.default!(key)
38
+ e = self.entity_storage[key]
39
+ assert_equal e, value
40
+
41
+ # set it to something else using method missing
42
+ if key[/\w/] == key
43
+ eval("e = self.entity_storage."+key +" = Time.now.to_s")
44
+ eval("e = self.entity_storage."+key)
45
+ assert_equal e, value
46
+ end
47
+ }
48
+ end
49
+
50
+ # tests setting values when no DEFAULT_KEY exists
51
+ def test_settingvalues
52
+ self.entity_storage.delete('test')
53
+
54
+ # key that can't be accessed via method missing
55
+ # set value and check it
56
+ self.entity_storage['big long key that cannot be accessed via method missing'] = 'what up'
57
+ e = self.entity_storage['big long key that cannot be accessed via method missing']
58
+ assert_equal e, 'what up'
59
+
60
+ # set another value and check it
61
+ self.entity_storage['big long key that cannot be accessed via method missing'] = 'another value'
62
+ e = self.entity_storage['big long key that cannot be accessed via method missing']
63
+ assert_equal e, 'another value'
64
+
65
+ self.entity_storage['test'] = 'what up'
66
+ e = self.entity_storage['test']
67
+ assert_equal e, 'what up'
68
+
69
+ self.entity_storage['test'] = 'another value'
70
+ e = self.entity_storage['test']
71
+ assert_equal e, 'another value'
72
+
73
+ # try the method missing version of the tests
74
+ e = self.entity_storage.test = 'what up'
75
+ e = self.entity_storage.test
76
+ assert_equal e, 'what up'
77
+
78
+ e = self.entity_storage.test = 'another value'
79
+ e = self.entity_storage.test
80
+ assert_equal e, 'another value'
81
+
82
+ end
83
+
84
+ def test_getunknownvalue
85
+ self.entity_storage.delete('does not exist')
86
+ e = self.entity_storage['does not exist']
87
+ assert_nil e
88
+ end
89
+
90
+ end
@@ -0,0 +1,6 @@
1
+ require 'stringio'
2
+ require 'test/unit'
3
+ require 'rubygems'
4
+ require 'active_record'
5
+ require 'active_support'
6
+ require File.dirname(__FILE__) + '/../lib/entity_storage'
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: eatenbyagrue-entity_storage
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Joshua Siler
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-09-20 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: activerecord
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.2.2
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: hoe
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 2.3.3
34
+ version:
35
+ description: An easy to use, persistent Key/Value store for any Ruby on Rails project. Designed to store config values & application wide state that need to survive server restarts. Additionally, allows users to set a list of default keys that auto-initiliazes baseline key/value pairs in the database for easy initialization.
36
+ email:
37
+ - joshua.siler@gmail.com
38
+ executables: []
39
+
40
+ extensions: []
41
+
42
+ extra_rdoc_files:
43
+ - History.txt
44
+ - Manifest.txt
45
+ files:
46
+ - History.txt
47
+ - Manifest.txt
48
+ - README.rdoc
49
+ - Rakefile
50
+ - lib/entity_storage.rb
51
+ - script/console
52
+ - script/destroy
53
+ - script/generate
54
+ - config/database.yml
55
+ - test/test_entity_storage.rb
56
+ - test/test_helper.rb
57
+ has_rdoc: false
58
+ homepage: http://github.com/eatenbyagrue/entity_storage
59
+ licenses:
60
+ post_install_message:
61
+ rdoc_options:
62
+ - --main
63
+ - README.rdoc
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: "0"
71
+ version:
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: "0"
77
+ version:
78
+ requirements: []
79
+
80
+ rubyforge_project: entity_storage
81
+ rubygems_version: 1.3.5
82
+ signing_key:
83
+ specification_version: 3
84
+ summary: An easy to use, persistent Key/Value store for any Ruby on Rails project
85
+ test_files:
86
+ - test/test_entity_storage.rb
87
+ - test/test_helper.rb