tobi-cached 0.5.0

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/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ == 0.0.1 2009-06-07
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
data/Manifest.txt ADDED
@@ -0,0 +1,18 @@
1
+ History.txt
2
+ Manifest.txt
3
+ PostInstall.txt
4
+ README.rdoc
5
+ Rakefile
6
+ cached.gemspec
7
+ init.rb
8
+ lib/cached.rb
9
+ lib/cached/config.rb
10
+ lib/cached/config_compiler.rb
11
+ lib/cached/model.rb
12
+ lib/cached/record.rb
13
+ test/people_database.rb
14
+ test/test_cached.rb
15
+ test/test_cached_delegation.rb
16
+ test/test_config_compiler.rb
17
+ test/test_helper.rb
18
+ test/test_record.rb
data/PostInstall.txt ADDED
File without changes
data/README.rdoc ADDED
@@ -0,0 +1,63 @@
1
+ = cached
2
+
3
+ * http://github.com/tobi/cached
4
+
5
+ == DESCRIPTION:
6
+
7
+ Small trial project that attempts to accelerate common active record like operations without too much black magic.
8
+
9
+
10
+ == SYNOPSIS:
11
+
12
+ class Product < AR:Base
13
+
14
+ cache_by_key :id do
15
+ index :name
16
+ index [:brand, :name]
17
+
18
+ delegate_to :find
19
+ end
20
+ end
21
+
22
+ Product.create :name => 'ipod', :brand => 'apple'
23
+
24
+ Product.lookup(1) # cache_hit, 1 memcached query
25
+ Product.lookup(2) # cache_miss, 1 memcached query, 1 db query: .find(2) (see delegates_to)
26
+ Product.lookup_by_name('ipod') # cache_hit, 2 memcached queries
27
+ Product.lookup_by_brand_and_name('apple','ipod') # cache_hit, 2 memcached queries
28
+
29
+ Product.lookup_by_something('else') # raise NoMethodError
30
+
31
+
32
+ == REQUIREMENTS:
33
+
34
+ * Active Record included with rails 2.3+
35
+
36
+ == INSTALL:
37
+
38
+ * Gem install or plugin install
39
+
40
+ == LICENSE:
41
+
42
+ (The MIT License)
43
+
44
+ Copyright (c) 2009 Tobias Lütke
45
+
46
+ Permission is hereby granted, free of charge, to any person obtaining
47
+ a copy of this software and associated documentation files (the
48
+ 'Software'), to deal in the Software without restriction, including
49
+ without limitation the rights to use, copy, modify, merge, publish,
50
+ distribute, sublicense, and/or sell copies of the Software, and to
51
+ permit persons to whom the Software is furnished to do so, subject to
52
+ the following conditions:
53
+
54
+ The above copyright notice and this permission notice shall be
55
+ included in all copies or substantial portions of the Software.
56
+
57
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
58
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
59
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
60
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
61
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
62
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
63
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,29 @@
1
+ BEGIN {$VERBOSE = nil;$DEBUG = nil}
2
+
3
+ require 'rubygems' unless ENV['NO_RUBYGEMS']
4
+ %w[rake rake/clean fileutils newgem rubigen].each { |f| require f }
5
+ require File.dirname(__FILE__) + '/lib/cached'
6
+
7
+ # Generate all the Rake tasks
8
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
9
+ $hoe = Hoe.new('cached', Cached::VERSION) do |p|
10
+ p.developer('Tobias Lütke', 'tobi@leetsoft.com')
11
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
12
+ p.extra_deps = [
13
+ ['activesupport','>= 2.3.2'],
14
+ ]
15
+
16
+ p.extra_dev_deps = [
17
+ ['newgem', ">= #{::Newgem::VERSION}"]
18
+ ]
19
+ p.clean_globs |= %w[**/.DS_Store tmp *.log]
20
+ path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
21
+ p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
22
+ p.rsync_args = '-av --delete --ignore-errors'
23
+ end
24
+
25
+ require 'newgem/tasks' # load /tasks/*.rake
26
+ Dir['tasks/**/*.rake'].each { |t| load t }
27
+
28
+ # TODO - want other tests/tasks run by default? Add them to the list
29
+ # task :default => [:spec, :features]
data/cached.gemspec ADDED
@@ -0,0 +1,41 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{cached}
5
+ s.version = "0.5.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Tobias L\303\274tke"]
9
+ s.date = %q{2009-06-10}
10
+ s.description = %q{Small trial project that attempts to accelerate common active record like operations without too much black magic.}
11
+ s.email = ["tobi@leetsoft.com"]
12
+ s.extra_rdoc_files = ["History.txt", "Manifest.txt", "PostInstall.txt", "README.rdoc"]
13
+ s.files = ["History.txt", "Manifest.txt", "PostInstall.txt", "README.rdoc", "Rakefile", "cached.gemspec", "init.rb", "lib/cached.rb", "lib/cached/config.rb", "lib/cached/config_compiler.rb", "lib/cached/model.rb", "lib/cached/record.rb", "test/people_database.rb", "test/test_cached.rb", "test/test_cached_delegation.rb", "test/test_config_compiler.rb", "test/test_helper.rb", "test/test_record.rb"]
14
+ s.has_rdoc = true
15
+ s.homepage = %q{http://github.com/tobi/cached}
16
+ s.rdoc_options = ["--main", "README.rdoc"]
17
+ s.require_paths = ["lib"]
18
+ s.rubyforge_project = %q{cached}
19
+ s.rubygems_version = %q{1.3.1}
20
+ s.summary = %q{Small trial project that attempts to accelerate common active record like operations without too much black magic.}
21
+ s.test_files = ["test/test_cached.rb", "test/test_cached_delegation.rb", "test/test_config_compiler.rb", "test/test_helper.rb", "test/test_record.rb"]
22
+
23
+ if s.respond_to? :specification_version then
24
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
25
+ s.specification_version = 2
26
+
27
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
28
+ s.add_runtime_dependency(%q<activesupport>, [">= 2.3.2"])
29
+ s.add_development_dependency(%q<newgem>, [">= 1.4.1"])
30
+ s.add_development_dependency(%q<hoe>, [">= 1.8.0"])
31
+ else
32
+ s.add_dependency(%q<activesupport>, [">= 2.3.2"])
33
+ s.add_dependency(%q<newgem>, [">= 1.4.1"])
34
+ s.add_dependency(%q<hoe>, [">= 1.8.0"])
35
+ end
36
+ else
37
+ s.add_dependency(%q<activesupport>, [">= 2.3.2"])
38
+ s.add_dependency(%q<newgem>, [">= 1.4.1"])
39
+ s.add_dependency(%q<hoe>, [">= 1.8.0"])
40
+ end
41
+ end
data/init.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'cached'
2
+
3
+ ActiveRecord::Base.send(:include, Cached::Model)
4
+ ActiveRecord::Base.send(:include, Cached::Record)
data/lib/cached.rb ADDED
@@ -0,0 +1,17 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require 'rubygems'
5
+ require 'active_support'
6
+
7
+ module Cached
8
+ VERSION = '0.5.0'
9
+
10
+ mattr_accessor :store
11
+ self.store = ActiveSupport::Cache.lookup_store(:memory_store)
12
+ end
13
+
14
+
15
+ require 'cached/config'
16
+ require 'cached/config_compiler'
17
+ require 'cached/model'
@@ -0,0 +1,18 @@
1
+ module Cached
2
+ class Config
3
+ attr_accessor :indexes, :class_name, :primary_key, :delegates
4
+
5
+ def initialize(class_name, primary_key)
6
+ @delegates, @indexes, @class_name, @primary_key = [], [], class_name.to_s, primary_key.to_s
7
+ end
8
+
9
+ def index(*args)
10
+ @indexes.push args.flatten
11
+ end
12
+
13
+ def delegate_to(*methods)
14
+ @delegates += methods.flatten
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,103 @@
1
+ module Cached
2
+
3
+ class ConfigCompiler
4
+
5
+ def initialize(config)
6
+ @config = config
7
+ end
8
+
9
+ def to_ruby
10
+ [compiled_meta_methods, compiled_save_methods, compiled_fetch_methods].join
11
+ end
12
+
13
+ def compiled_meta_methods
14
+
15
+ # Instance methods
16
+ "def object_cache_primary_key; \"#{@config.primary_key}\"; end;" +
17
+ "def object_cache_key; \"\#{object_cache_prefix}:\#{#{@config.primary_key}}\"; end;" +
18
+ "def object_cache_prefix; \"#{@config.class_name}\"; end;" +
19
+ "def object_cache_hash(*args); args.join.hash; end;" +
20
+
21
+ # Class methods
22
+ "def self.object_cache_prefix; \"#{@config.class_name}\"; end;" +
23
+ "def self.object_cache_hash(*args); args.join.hash; end;"
24
+ end
25
+
26
+ def compiled_save_methods
27
+ compiled_save_object_method + compiled_save_index_method
28
+ end
29
+
30
+ def compiled_save_object_method
31
+ "def save_object_to_cache;" +
32
+ "Cached.store.write(object_cache_key, self);" +
33
+ "end;" +
34
+
35
+ "def expire_object_in_cache;" +
36
+ "Cached.store.delete(object_cache_key);" +
37
+ "end;"
38
+ end
39
+
40
+ def compiled_save_index_method
41
+
42
+ keys = @config.indexes.collect { |index| index_cache_key(index) }
43
+
44
+ "def save_indexes_to_cache;" +
45
+ "v = #{@config.primary_key};" +
46
+ keys.collect{|k| "Cached.store.write(#{k}, v);"}.join +
47
+ "end;" +
48
+
49
+ "def expire_indexes_in_cache;" +
50
+ keys.collect{|k| "Cached.store.delete(#{k});"}.join +
51
+ "end;"
52
+ end
53
+
54
+ def compiled_fetch_method_for(index)
55
+ index_name = index_name(index)
56
+ cache_key = index_cache_key(index)
57
+
58
+ method_suffix_and_parameters = "#{index_name}(#{index.join(', ')})"
59
+
60
+ delegation = @config.delegates.collect { |delegate| "|| #{delegate}_by_#{method_suffix_and_parameters}" }
61
+
62
+ "def self.lookup_by_#{method_suffix_and_parameters};" +
63
+ " if key = Cached.store.read(#{cache_key});"+
64
+ " lookup(key);"+
65
+ " else;"+
66
+ " obj = nil #{delegation};" +
67
+ " obj.save_indexes_to_cache if obj.respond_to?(:save_indexes_to_cache);" +
68
+ " obj;" +
69
+ " end;" +
70
+ "end;"
71
+ end
72
+
73
+ def compiled_fetch_method_for_primary_key
74
+
75
+ delegation = @config.delegates.collect{|c| "|| #{c}(pk)" }.join
76
+
77
+ "def self.lookup(pk);" +
78
+ " Cached.store.fetch(\"#\{object_cache_prefix}:#\{pk}\") { nil #{delegation} };" +
79
+ "end;" +
80
+
81
+
82
+ "def self.lookup_by_#{@config.primary_key}(pk);" +
83
+ " lookup(pk); "+
84
+ "end;"
85
+ end
86
+
87
+ def compiled_fetch_methods
88
+ compiled_fetch_method_for_primary_key + @config.indexes.collect { |index| compiled_fetch_method_for(index) }.join(';')
89
+ end
90
+
91
+ private
92
+
93
+ def index_cache_key(index)
94
+ "\"#\{object_cache_prefix}/#{index_name(index)}:#\{object_cache_hash(#{index.join(', ')})}\""
95
+ end
96
+
97
+ def index_name(index)
98
+ index.collect(&:to_s).collect(&:downcase).collect(&:underscore).join('_and_')
99
+ end
100
+ end
101
+
102
+
103
+ end
@@ -0,0 +1,27 @@
1
+ module Cached
2
+
3
+ module Model
4
+
5
+ module ClassMethods
6
+ def cache_by_key(primary_key, &block)
7
+ config = Config.new(name.underscore.downcase, primary_key)
8
+ config.instance_eval(&block)
9
+
10
+ self.class_eval ConfigCompiler.new(config).to_ruby, __FILE__, __LINE__
11
+ end
12
+ end
13
+
14
+ def self.included(base)
15
+ base.extend ClassMethods
16
+ end
17
+
18
+
19
+ def save_to_cache
20
+ save_object_to_cache
21
+ save_indexes_to_cache
22
+ end
23
+
24
+ end
25
+
26
+
27
+ end
@@ -0,0 +1,25 @@
1
+ module Cached
2
+ module Record
3
+
4
+ def self.included?(base)
5
+
6
+ if base.respond_to?(:save)
7
+ base.alias_method_chain :save, :cached
8
+ end
9
+
10
+ end
11
+
12
+
13
+ def save_with_cached
14
+ save_without_cached
15
+
16
+ # expire the cache, the object will be stored in it's prestine form
17
+ # after the next lookup call hopefull.
18
+ expire_object_in_cache
19
+
20
+ # update the indexes for the new values.
21
+ store_indexes_in_cache
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,12 @@
1
+ require 'active_record'
2
+
3
+ ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => '/tmp/people.db')
4
+
5
+ ActiveRecord::Schema.define do
6
+
7
+ create_table :people, :force => true do |t|
8
+ t.column :first_name, :string
9
+ t.column :last_name, :string
10
+ end
11
+ end
12
+
@@ -0,0 +1,85 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class Product < Struct.new(:id, :name, :price, :vendor)
4
+ include Cached::Model
5
+
6
+ cache_by_key :id do
7
+ index :name
8
+ index [:vendor, :name]
9
+ end
10
+
11
+ end
12
+
13
+
14
+ class TestCached < Test::Unit::TestCase
15
+
16
+ def setup
17
+ @product = Product.new(1, 'ipod', 149.00, 'apple')
18
+ end
19
+
20
+ context "cache storage" do
21
+
22
+ test "product can be stored to cache" do
23
+ @product.respond_to?(:save_to_cache)
24
+ end
25
+
26
+ test "product stores meta data in instance methods" do
27
+ assert_equal "id", @product.object_cache_primary_key
28
+ end
29
+
30
+ test "product has efficient object_cache_key instance method" do
31
+ assert_equal "product:1", @product.object_cache_key
32
+ end
33
+
34
+ test "product stores itself to memcached on save_to_cache call" do
35
+ assert @product.save_to_cache
36
+ assert_equal @product, Cached.store.read('product:1')
37
+ end
38
+
39
+ test "product stores defined indexes as backreference to product key" do
40
+ assert @product.save_to_cache
41
+ assert_equal 1, Cached.store.read("product/name:#{hash('ipod')}")
42
+ assert_equal 1, Cached.store.read("product/vendor_and_name:#{hash('appleipod')}")
43
+ end
44
+
45
+ end
46
+
47
+ context "lookups" do
48
+
49
+ test "product explicit lookup by primary_key" do
50
+ @product.save_to_cache
51
+ Cached.store.expects(:read).with('product:1', {})
52
+ Product.lookup_by_id(1)
53
+ end
54
+
55
+ test "product lookup by primary_key" do
56
+ @product.save_to_cache
57
+ Cached.store.expects(:read).with('product:1', {})
58
+ Product.lookup(1)
59
+ end
60
+
61
+ test "product lookup by index" do
62
+ @product.save_to_cache
63
+ Cached.store.expects(:read).with("product/name:#{hash('ipod')}").returns(1)
64
+ Cached.store.expects(:read).with('product:1', {})
65
+ Product.lookup_by_name('ipod')
66
+ end
67
+
68
+ test "product lookup by multi index" do
69
+ @product.save_to_cache
70
+ Cached.store.expects(:read).with("product/vendor_and_name:#{hash('appleipod')}").returns(1)
71
+ Cached.store.expects(:read).with('product:1', {})
72
+ Product.lookup_by_vendor_and_name('apple', 'ipod')
73
+ end
74
+
75
+ end
76
+
77
+ private
78
+
79
+ def hash(text)
80
+ text.hash
81
+ end
82
+
83
+ end
84
+
85
+
@@ -0,0 +1,41 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+
4
+ class DelegatingProduct < Struct.new(:id, :name, :price, :vendor)
5
+ include Cached::Model
6
+
7
+ cache_by_key :id do
8
+ index :name
9
+ index [:vendor, :name]
10
+
11
+ delegate_to :find
12
+ end
13
+ end
14
+
15
+ class TestCachedDelegation < Test::Unit::TestCase
16
+
17
+ def setup
18
+ @delegating_product = DelegatingProduct.new(1, 'ipod', 149.00, 'apple')
19
+ end
20
+
21
+
22
+ test "lookup miss will delegate to find method" do
23
+ DelegatingProduct.expects(:find).with(2)
24
+ DelegatingProduct.lookup(2)
25
+ end
26
+
27
+ test "lookup by index miss will delegate to find_by_index method" do
28
+ DelegatingProduct.expects(:find).with(2)
29
+ DelegatingProduct.lookup(2)
30
+ end
31
+
32
+ private
33
+
34
+ def hash(text)
35
+ text.hash
36
+ end
37
+
38
+ end
39
+
40
+
41
+
@@ -0,0 +1,53 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestConfigCompiler < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @dump = Class.new
7
+ @config = Cached::ConfigCompiler.new(Cached::Config.new('product', 'id'))
8
+ end
9
+
10
+ test "syntax compiled_meta_methods" do
11
+ @dump.instance_eval @config.compiled_meta_methods
12
+ @dump.respond_to?(:object_cache_primary_key)
13
+ @dump.respond_to?(:object_cache_key)
14
+ @dump.respond_to?(:object_cache_prefix)
15
+ @dump.respond_to?(:object_cache_hash)
16
+ end
17
+
18
+ test "syntax compiled_save_object_method" do
19
+ @dump.instance_eval @config.compiled_save_object_method
20
+
21
+ @dump.respond_to?(:save_object_to_cache)
22
+ end
23
+
24
+ test "syntax compiled_save_index_method" do
25
+ @dump.instance_eval @config.compiled_save_index_method
26
+
27
+ @dump.respond_to?(:save_indexes_to_cache)
28
+ end
29
+
30
+ test "syntax compiled_fetch_method_for single column" do
31
+ @dump.instance_eval @config.compiled_fetch_method_for([:name])
32
+
33
+ @dump.respond_to?(:lookup_by_name)
34
+ end
35
+
36
+ test "syntax compiled_fetch_method_for multi column" do
37
+ @dump.instance_eval @config.compiled_fetch_method_for([:name, :brand])
38
+
39
+ @dump.respond_to?(:lookup_by_name_and_brand)
40
+ end
41
+
42
+ test "syntax compiled_fetch_method_for_primary_key" do
43
+ @dump.instance_eval @config.compiled_fetch_method_for_primary_key
44
+
45
+ @dump.respond_to?(:lookup)
46
+ @dump.respond_to?(:lookup_by_id)
47
+ end
48
+
49
+ test "all syntax" do
50
+ @dump.instance_eval @config.to_ruby
51
+ end
52
+
53
+ end
@@ -0,0 +1,24 @@
1
+ require 'stringio'
2
+ require 'test/unit'
3
+ require 'rubygems'
4
+ require 'mocha'
5
+ require File.dirname(__FILE__) + '/../lib/cached'
6
+
7
+ require 'active_support/cache'
8
+ require 'active_record'
9
+
10
+ Cached.store = ActiveSupport::Cache.lookup_store(:memory_store)
11
+ #Cached.store = ActiveSupport::Cache.lookup_store(:mem_cache_store)
12
+
13
+
14
+ class Test::Unit::TestCase
15
+
16
+ def self.test(string, &block)
17
+ define_method("test:#{string}", &block)
18
+ end
19
+
20
+ def self.context(string)
21
+ yield
22
+ end
23
+
24
+ end
@@ -0,0 +1,56 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+ require File.dirname(__FILE__) + '/people_database'
3
+
4
+ require 'cached/record'
5
+
6
+ class Person < ActiveRecord::Base
7
+ include Cached::Model
8
+ include Cached::Record
9
+
10
+ def name
11
+ "#{first_name} #{last_name}"
12
+ end
13
+
14
+ cache_by_key :id do
15
+ index :first_name
16
+ index :last_name
17
+ index [:first_name, :last_name]
18
+
19
+ delegate_to :find
20
+ end
21
+ end
22
+
23
+ class TestRecord < Test::Unit::TestCase
24
+
25
+ def setup
26
+ @bob = Person.create(:first_name => 'Bob', :last_name => 'Bobsen')
27
+ end
28
+
29
+ test "cachemiss delegates to find" do
30
+ assert !Cached.store.read("person:1")
31
+ assert_equal @bob, Person.lookup(@bob.id)
32
+ end
33
+
34
+ test "load bob from cache store" do
35
+ @bob.save_to_cache
36
+
37
+ assert_equal @bob, Person.lookup_by_first_name('Bob')
38
+ assert_equal @bob, Person.lookup_by_last_name('Bobsen')
39
+ assert_equal @bob, Person.lookup_by_first_name_and_last_name('Bob', 'Bobsen')
40
+ end
41
+
42
+ test "cache miss on index query will make returned object re-save its indexes" do
43
+ assert !Cached.store.read("person/first_name:#{hash('Bob')}")
44
+ assert_equal @bob, Person.lookup_by_first_name('Bob')
45
+
46
+ assert Cached.store.read("person/first_name:#{hash('Bob')}")
47
+ end
48
+
49
+
50
+ private
51
+
52
+ def hash(text)
53
+ text.hash
54
+ end
55
+
56
+ end
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tobi-cached
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.0
5
+ platform: ruby
6
+ authors:
7
+ - "Tobias L\xC3\xBCtke"
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-06-10 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: activesupport
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.3.2
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: newgem
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.4.1
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: hoe
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 1.8.0
44
+ version:
45
+ description: Small trial project that attempts to accelerate common active record like operations without too much black magic.
46
+ email:
47
+ - tobi@leetsoft.com
48
+ executables: []
49
+
50
+ extensions: []
51
+
52
+ extra_rdoc_files:
53
+ - History.txt
54
+ - Manifest.txt
55
+ - PostInstall.txt
56
+ - README.rdoc
57
+ files:
58
+ - History.txt
59
+ - Manifest.txt
60
+ - PostInstall.txt
61
+ - README.rdoc
62
+ - Rakefile
63
+ - cached.gemspec
64
+ - init.rb
65
+ - lib/cached.rb
66
+ - lib/cached/config.rb
67
+ - lib/cached/config_compiler.rb
68
+ - lib/cached/model.rb
69
+ - lib/cached/record.rb
70
+ - test/people_database.rb
71
+ - test/test_cached.rb
72
+ - test/test_cached_delegation.rb
73
+ - test/test_config_compiler.rb
74
+ - test/test_helper.rb
75
+ - test/test_record.rb
76
+ has_rdoc: true
77
+ homepage: http://github.com/tobi/cached
78
+ post_install_message:
79
+ rdoc_options:
80
+ - --main
81
+ - README.rdoc
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: "0"
89
+ version:
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: "0"
95
+ version:
96
+ requirements: []
97
+
98
+ rubyforge_project: cached
99
+ rubygems_version: 1.2.0
100
+ signing_key:
101
+ specification_version: 2
102
+ summary: Small trial project that attempts to accelerate common active record like operations without too much black magic.
103
+ test_files:
104
+ - test/test_cached.rb
105
+ - test/test_cached_delegation.rb
106
+ - test/test_config_compiler.rb
107
+ - test/test_helper.rb
108
+ - test/test_record.rb