machinist-caching 0.0.1

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.
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --tty
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ source "http://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in machinist-caching.gemspec
6
+ gemspec
7
+
8
+ gem 'machinist', :git => 'https://github.com/notahat/machinist.git'
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new
5
+
6
+ task :default => :spec
@@ -0,0 +1,17 @@
1
+ require 'machinist'
2
+
3
+ module Machinist
4
+ module Caching
5
+ autoload :Machinable, 'machinist/caching/machinable'
6
+ autoload :Shop, 'machinist/caching/shop'
7
+ autoload :Warehouse, 'machinist/caching/warehouse'
8
+
9
+ module ActiveRecord
10
+ autoload :Blueprint, 'machinist/caching/active_record/blueprint'
11
+ end
12
+ end
13
+
14
+ module Machinable #:nodoc:
15
+ extend Machinist::Caching::Machinable
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ require 'machinist/caching'
2
+ require 'machinist/active_record'
3
+
4
+ module Machinist #:nodoc:
5
+ module ActiveRecord
6
+ class Blueprint
7
+ include Machinist::Caching::ActiveRecord::Blueprint
8
+ end
9
+ end
10
+ end
11
+
12
+ module ActiveRecord #:nodoc:
13
+ class Base
14
+ extend Machinist::Caching::Machinable
15
+ end
16
+ end
@@ -0,0 +1,17 @@
1
+ module Machinist
2
+ module Caching
3
+ module ActiveRecord
4
+ module Blueprint
5
+ # Box an object for storage in the warehouse.
6
+ def box(object)
7
+ object.id
8
+ end
9
+
10
+ # Unbox an object from the warehouse.
11
+ def unbox(id)
12
+ @klass.find(id)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ module Machinist
2
+ module Caching
3
+ module Machinable
4
+ # Construct and save an object from a blueprint, if the class allows saving.
5
+ #
6
+ # :call-seq:
7
+ # make!([count], [blueprint_name], [attributes = {}])
8
+ #
9
+ # A cached object will be returned from the shop if possible. See
10
+ # Machinist::Caching::Shop.
11
+ #
12
+ # Arguments are the same as for make.
13
+ def make!(*args)
14
+ decode_args_to_make(*args) do |blueprint, attributes|
15
+ Shop.instance.buy(blueprint, attributes)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,45 @@
1
+ require 'singleton'
2
+
3
+ module Machinist
4
+ module Caching
5
+ # The shop takes care of caching database objects.
6
+ #
7
+ # Calling make! on a class requests objects from the shop; you don't
8
+ # normally access the shop directly.
9
+ #
10
+ # Read more about object caching on the
11
+ # wiki[http://wiki.github.com/notahat/machinist/object-caching].
12
+ class Shop
13
+ include Singleton
14
+
15
+ attr_accessor :warehouse
16
+
17
+ def initialize #:nodoc:
18
+ reset!
19
+ end
20
+
21
+ # Throw out the entire collection of cached objects.
22
+ def reset!
23
+ self.warehouse = Warehouse.new
24
+ end
25
+
26
+ # Buy a (possibly cached) object from the shop.
27
+ #
28
+ # This is just like constructing an object by calling Blueprint#make!,
29
+ # but it will return a previously cached object if one is available.
30
+ def buy(blueprint, attributes = {})
31
+ raise BlueprintCantSaveError.new(blueprint) unless blueprint.respond_to?(:make!)
32
+
33
+ cached = warehouse[blueprint, attributes]
34
+
35
+ if cached.nil?
36
+ blueprint.make!(attributes).tap do |object|
37
+ warehouse[blueprint, attributes] = blueprint.box(object)
38
+ end
39
+ else
40
+ blueprint.unbox(cached)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,27 @@
1
+ module Machinist
2
+ module Caching
3
+ # A Warehouse is a hash supports lists as keys.
4
+ #
5
+ # It's used for storing cached objects created by Machinist::Caching::Shop.
6
+ #
7
+ # warehouse[klass, attributes] = object
8
+ # warehouse[klass, attributes] # => object
9
+ class Warehouse
10
+ attr_accessor :shelf
11
+
12
+ def initialize #:nodoc:
13
+ self.shelf = Hash.new{|hash, key| hash[key] = {}}
14
+ end
15
+
16
+ # Assign a value for the given list of keys.
17
+ def []=(klass, attributes, object)
18
+ shelf[klass][attributes] = object
19
+ end
20
+
21
+ # Return the value for the given list of keys.
22
+ def [](klass, attributes)
23
+ shelf[klass][attributes]
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ Gem::Specification.new do |s|
3
+ s.name = "machinist-caching"
4
+ s.version = "0.0.1"
5
+ s.authors = ["Tomas D'Stefano", "Gabriel Sobrinho"]
6
+ s.email = ["tomas_stefano@successoft.com", "gabriel.sobrinho@gmail.com"]
7
+ s.homepage = "https://github.com/tomas-stefano/machinist-caching"
8
+ s.summary = %q{Object caching for machinist}
9
+ s.description = %q{Object caching for machinist}
10
+
11
+ s.files = `git ls-files`.split("\n")
12
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
13
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
14
+ s.require_paths = ["lib"]
15
+
16
+ s.add_development_dependency 'rspec', '>= 2.6.0'
17
+ s.add_development_dependency 'activerecord', '>= 3.0'
18
+ s.add_development_dependency 'mysql', '>= 2.8.1'
19
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe Machinist::Caching::ActiveRecord::Blueprint do
4
+ let :blueprint do
5
+ Machinist::ActiveRecord::Blueprint.new(Post) {}
6
+ end
7
+
8
+ let :post do
9
+ Post.make!
10
+ end
11
+
12
+ it 'should box object using id' do
13
+ blueprint.box(post).should == post.id
14
+ end
15
+
16
+ it 'should unbox object using id' do
17
+ blueprint.unbox(post.id).should == post
18
+ end
19
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe Machinist::Caching::Machinable do
4
+ it 'should buy objects from the shop' do
5
+ post_a = Post.make!
6
+ post_b = Post.make!
7
+
8
+ post_a.should == post_b
9
+ end
10
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe Machinist::Caching::Shop do
4
+ let :shop do
5
+ Machinist::Caching::Shop.instance
6
+ end
7
+
8
+ it 'should cache an object' do
9
+ blueprint = Machinist::ActiveRecord::Blueprint.new(Post) {}
10
+
11
+ object_a = shop.buy(blueprint)
12
+ object_b = shop.buy(blueprint)
13
+
14
+ object_a.should == object_b
15
+ end
16
+
17
+ it 'should cache an object with attributes' do
18
+ blueprint = Machinist::ActiveRecord::Blueprint.new(Post) {}
19
+
20
+ object_a = shop.buy(blueprint, :title => 'Lorem ipsum')
21
+ object_b = shop.buy(blueprint, :title => 'Lorem ipsum')
22
+
23
+ object_a.should == object_b
24
+ end
25
+
26
+ it 'should not confuse objects with different blueprints' do
27
+ blueprint_a = Machinist::ActiveRecord::Blueprint.new(Post) {}
28
+ blueprint_b = Machinist::ActiveRecord::Blueprint.new(Post) {}
29
+
30
+ object_a = shop.buy(blueprint_a, :title => 'Lorem ipsum')
31
+ object_b = shop.buy(blueprint_b, :title => 'Lorem ipsum')
32
+
33
+ object_a.should_not == object_b
34
+ end
35
+
36
+ it 'should not confuse objects with same blueprint but different attributes' do
37
+ blueprint = Machinist::ActiveRecord::Blueprint.new(Post) {}
38
+
39
+ object_a = shop.buy(blueprint, :title => 'Lorem ipsum')
40
+ object_b = shop.buy(blueprint, :title => 'Lorem ipsum dolor sit amet')
41
+
42
+ object_a.should_not == object_b
43
+ end
44
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe Machinist::Caching::Warehouse do
4
+ let :warehouse do
5
+ Machinist::Caching::Warehouse.new
6
+ end
7
+
8
+ it 'should return nil for a new key' do
9
+ warehouse['klass', 'attributes'].should == nil
10
+ end
11
+
12
+ it 'should store and retrieve values' do
13
+ warehouse['klass', 'attributes'] = 'object'
14
+ warehouse['klass', 'attributes'].should == 'object'
15
+ end
16
+ end
@@ -0,0 +1,32 @@
1
+ require 'rspec'
2
+ require 'machinist/caching/active_record'
3
+
4
+ ActiveRecord::Base.establish_connection(
5
+ :adapter => "mysql",
6
+ :database => "machinist",
7
+ :username => "root",
8
+ :password => ""
9
+ )
10
+
11
+ ActiveRecord::Migration.verbose = false
12
+
13
+ ActiveRecord::Schema.define(:version => 0) do
14
+ create_table :posts, :force => true do |t|
15
+ t.column :title, :string
16
+ t.column :body, :text
17
+ end
18
+ end
19
+
20
+ class Post < ActiveRecord::Base
21
+ end
22
+
23
+ Post.blueprint do
24
+ title { 'Lorem ipsum' }
25
+ body { 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.' }
26
+ end
27
+
28
+ RSpec.configure do |config|
29
+ config.before do
30
+ Machinist::Caching::Shop.instance.reset!
31
+ end
32
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: machinist-caching
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Tomas D'Stefano
9
+ - Gabriel Sobrinho
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+
14
+ date: 2011-07-14 00:00:00 -03:00
15
+ default_executable:
16
+ dependencies:
17
+ - !ruby/object:Gem::Dependency
18
+ name: rspec
19
+ prerelease: false
20
+ requirement: &id001 !ruby/object:Gem::Requirement
21
+ none: false
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: 2.6.0
26
+ type: :development
27
+ version_requirements: *id001
28
+ - !ruby/object:Gem::Dependency
29
+ name: activerecord
30
+ prerelease: false
31
+ requirement: &id002 !ruby/object:Gem::Requirement
32
+ none: false
33
+ requirements:
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: "3.0"
37
+ type: :development
38
+ version_requirements: *id002
39
+ - !ruby/object:Gem::Dependency
40
+ name: mysql
41
+ prerelease: false
42
+ requirement: &id003 !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 2.8.1
48
+ type: :development
49
+ version_requirements: *id003
50
+ description: Object caching for machinist
51
+ email:
52
+ - tomas_stefano@successoft.com
53
+ - gabriel.sobrinho@gmail.com
54
+ executables: []
55
+
56
+ extensions: []
57
+
58
+ extra_rdoc_files: []
59
+
60
+ files:
61
+ - .gitignore
62
+ - .rspec
63
+ - Gemfile
64
+ - Rakefile
65
+ - lib/machinist/caching.rb
66
+ - lib/machinist/caching/active_record.rb
67
+ - lib/machinist/caching/active_record/blueprint.rb
68
+ - lib/machinist/caching/machinable.rb
69
+ - lib/machinist/caching/shop.rb
70
+ - lib/machinist/caching/warehouse.rb
71
+ - machinist-caching.gemspec
72
+ - spec/machinist/caching/active_record/blueprint_spec.rb
73
+ - spec/machinist/caching/machinable_spec.rb
74
+ - spec/machinist/caching/shop_spec.rb
75
+ - spec/machinist/caching/warehouse_spec.rb
76
+ - spec/spec_helper.rb
77
+ has_rdoc: true
78
+ homepage: https://github.com/tomas-stefano/machinist-caching
79
+ licenses: []
80
+
81
+ post_install_message:
82
+ rdoc_options: []
83
+
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ none: false
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: "0"
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: "0"
98
+ requirements: []
99
+
100
+ rubyforge_project:
101
+ rubygems_version: 1.5.2
102
+ signing_key:
103
+ specification_version: 3
104
+ summary: Object caching for machinist
105
+ test_files:
106
+ - spec/machinist/caching/active_record/blueprint_spec.rb
107
+ - spec/machinist/caching/machinable_spec.rb
108
+ - spec/machinist/caching/shop_spec.rb
109
+ - spec/machinist/caching/warehouse_spec.rb
110
+ - spec/spec_helper.rb