generation_cacheable 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/.rspec +2 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/ChangeLog +2 -0
  7. data/Gemfile +16 -0
  8. data/README.md +33 -0
  9. data/Rakefile +8 -0
  10. data/generation_cacheable.gemspec +23 -0
  11. data/lib/gen_cache.rb +32 -0
  12. data/lib/gen_cache/cache_io/fetching.rb +78 -0
  13. data/lib/gen_cache/cache_io/formatting.rb +75 -0
  14. data/lib/gen_cache/cache_io/parsing.rb +66 -0
  15. data/lib/gen_cache/cache_types/association_cache.rb +50 -0
  16. data/lib/gen_cache/cache_types/attribute_cache.rb +30 -0
  17. data/lib/gen_cache/cache_types/class_method_cache.rb +23 -0
  18. data/lib/gen_cache/cache_types/key_cache.rb +14 -0
  19. data/lib/gen_cache/cache_types/method_cache.rb +28 -0
  20. data/lib/gen_cache/caches.rb +15 -0
  21. data/lib/gen_cache/expiry.rb +37 -0
  22. data/lib/gen_cache/keys.rb +70 -0
  23. data/lib/gen_cache/version.rb +3 -0
  24. data/spec/gen_cache/cache_io/fetching_spec.rb +41 -0
  25. data/spec/gen_cache/cache_io/formatting_spec.rb +59 -0
  26. data/spec/gen_cache/cache_io/parsing_spec.rb +47 -0
  27. data/spec/gen_cache/cache_types/association_cache_spec.rb +313 -0
  28. data/spec/gen_cache/cache_types/attribute_cache_spec.rb +98 -0
  29. data/spec/gen_cache/cache_types/class_method_cache_spec.rb +72 -0
  30. data/spec/gen_cache/cache_types/key_cache_spec.rb +34 -0
  31. data/spec/gen_cache/cache_types/method_cache_spec.rb +108 -0
  32. data/spec/gen_cache/expiry_spec.rb +182 -0
  33. data/spec/gen_cache/keys_spec.rb +66 -0
  34. data/spec/gen_cache_spec.rb +76 -0
  35. data/spec/models/account.rb +7 -0
  36. data/spec/models/comment.rb +9 -0
  37. data/spec/models/descendant.rb +20 -0
  38. data/spec/models/group.rb +6 -0
  39. data/spec/models/image.rb +11 -0
  40. data/spec/models/location.rb +3 -0
  41. data/spec/models/post.rb +31 -0
  42. data/spec/models/tag.rb +6 -0
  43. data/spec/models/user.rb +54 -0
  44. data/spec/spec_helper.rb +96 -0
  45. metadata +149 -0
@@ -0,0 +1,66 @@
1
+ require 'spec_helper'
2
+
3
+ describe GenCache do
4
+ let(:cache) { Rails.cache }
5
+ let(:user) { User.create(:login => 'flyerhzm') }
6
+
7
+ context "methods" do
8
+
9
+ it "should generate a model prefix" do
10
+ schema_string = User.columns.sort_by(&:name).map { |c| "#{c.name}:#{c.type}"}.join(",")
11
+ schema_hash = CityHash.hash64(schema_string)
12
+ prefix = GenCache.model_prefix(User)
13
+ prefix.should == "users/#{schema_hash}"
14
+ end
15
+
16
+ it "should generate an instance prefix" do
17
+ attribute_string = user.attributes.sort.map { |k,v| [k,v].join(":")}.join(",")
18
+ attribute_hash = CityHash.hash64(attribute_string)
19
+ prefix = GenCache.instance_prefix(user)
20
+ prefix.should == GenCache.model_prefix(User) + "/#{user.id.to_s}/#{attribute_hash}"
21
+ end
22
+
23
+ it "should generate an instance key" do
24
+ expected_key = {type: :object, key: GenCache.model_prefix(User) + "/#{user.id.to_s}"}
25
+ GenCache.instance_key(User, user.id).should == expected_key
26
+ end
27
+
28
+ it "should generate an attribute key" do
29
+ expected_key = {type: :object, key: GenCache.model_prefix(User) + '/login/pathouse'}
30
+ att_key = GenCache.attribute_key(User, :login, ['pathouse'])
31
+ att_key.should == expected_key
32
+ end
33
+
34
+ it "should generate an all w/ attribute key" do
35
+ expected_key = {type: :object, key: GenCache.model_prefix(User) + "/all/login/pathouse"}
36
+ att_key = GenCache.attribute_key(User, :login, ['pathouse'], all: true)
37
+ att_key.should == expected_key
38
+ end
39
+
40
+ it "should generate a class method key" do
41
+ expected_key = {type: :method, key: GenCache.model_prefix(User) + "/default_name"}
42
+ cmethod_key = GenCache.class_method_key(User, :default_name)
43
+ cmethod_key.should == expected_key
44
+ end
45
+
46
+ it "should return all class method keys" do
47
+ all_cmethod_keys = GenCache.all_class_method_keys(User)
48
+ comparison = User.cached_class_methods.map do |cmeth|
49
+ GenCache.class_method_key(User, cmeth)
50
+ end
51
+ all_cmethod_keys.should == comparison
52
+ end
53
+
54
+ it "should generate a method key" do
55
+ expected_key = {type: :method, key: GenCache.instance_prefix(user) + "/last_post"}
56
+ method_key = GenCache.method_key(user, :last_post)
57
+ method_key.should == expected_key
58
+ end
59
+
60
+ it "should generate an association key" do
61
+ expected_key = {type: :association, key: GenCache.instance_prefix(user) + "/posts"}
62
+ assoc_key = GenCache.association_key(user, :posts)
63
+ assoc_key.should == expected_key
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,76 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cacheable do
4
+ let(:cache) { Rails.cache }
5
+ let(:user) { User.create(:login => 'flyerhzm') }
6
+
7
+ before :all do
8
+ @group1 = Group.create(name: "Ruby On Rails")
9
+ @account = user.create_account(group: @group1)
10
+ @post1 = user.posts.create(:title => 'post1')
11
+ @image1 = @post1.images.create
12
+ @comment1 = @post1.comments.create
13
+ @tag1 = @post1.tags.create(title: "Rails")
14
+ end
15
+
16
+ before :each do
17
+ cache.clear
18
+ user.reload
19
+ end
20
+
21
+ context "Association Expires on Save" do
22
+ it "should delete has_many with_association cache" do
23
+ user.cached_posts
24
+ key = Cacheable.association_key(user, :posts)
25
+ Rails.cache.read(key[:key]).should_not be_nil
26
+ @post1.update_attribute(:title, "Blarg")
27
+ old_key = Rails.cache.read(key[:key]).first
28
+ Rails.cache.read(old_key[:key]).should be_nil
29
+ end
30
+
31
+ it "should delete has_many with polymorphic with_association cache" do
32
+ @post1.cached_comments
33
+ key = Cacheable.association_key(@post1, :comments)
34
+ Rails.cache.read(key[:key]).should_not be_nil
35
+ @comment1.update_attribute(:commentable_type, "fart")
36
+ old_key = Rails.cache.read(key[:key]).first
37
+ Rails.cache.read(old_key[:key]).should be_nil
38
+ end
39
+
40
+ it "should delete has_many through with_association cache" do
41
+ user.cached_images
42
+ key = Cacheable.association_key(user, :images)
43
+ Rails.cache.read(key[:key]).should_not be_nil
44
+ @image1.update_attribute(:viewable_type, "Gralb")
45
+ old_key = Rails.cache.read(key[:key]).first
46
+ Rails.cache.read(old_key[:key]).should be_nil
47
+ end
48
+
49
+ it "should delete has_one with_association cache" do
50
+ user.cached_account
51
+ key = Cacheable.association_key(user, :account)
52
+ Rails.cache.read(key[:key]).should_not be_nil
53
+ @account.update_attribute(:group_id, 7)
54
+ old_key = Rails.cache.read(key[:key]).first
55
+ Rails.cache.read(old_key[:key]).should be_nil
56
+ end
57
+
58
+ it "should delete has_and_belongs_to_many with_association cache" do
59
+ @post1.cached_tags
60
+ key = Cacheable.association_key(@post1, :tags)
61
+ Rails.cache.read(key[:key]).should_not be_nil
62
+ old_key = Rails.cache.read(key[:key]).first
63
+ @tag1.update_attribute(:title, "new title")
64
+ Rails.cache.read(old_key[:key]).should be_nil
65
+ end
66
+
67
+ it "should delete has_one through belongs_to with_association cache" do
68
+ @account.update_attribute(:group_id, 1)
69
+ @group1.update_attribute(:name, "Poop Group")
70
+ key = Cacheable.association_key(user, :group)
71
+ Rails.cache.read(key[:key]).should be_nil
72
+ user.cached_group.should == @group1
73
+ Rails.cache.read(key[:key]).should == [Cacheable.instance_key(Group, @group1.id)]
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,7 @@
1
+ class Account < ActiveRecord::Base
2
+ include Cacheable
3
+
4
+ belongs_to :user
5
+
6
+ belongs_to :group
7
+ end
@@ -0,0 +1,9 @@
1
+ class Comment < ActiveRecord::Base
2
+ include Cacheable
3
+
4
+ belongs_to :commentable, :polymorphic => true
5
+
6
+ model_cache do
7
+ with_association :commentable
8
+ end
9
+ end
@@ -0,0 +1,20 @@
1
+ class Descendant < User
2
+
3
+ belongs_to :location
4
+
5
+ model_cache do
6
+ with_attribute :email
7
+ with_method :name
8
+ with_association :location
9
+ with_class_method :default_name
10
+ end
11
+
12
+ def name
13
+ "ScotterC"
14
+ end
15
+
16
+ def self.default_name
17
+ "ScotterC"
18
+ end
19
+
20
+ end
@@ -0,0 +1,6 @@
1
+ class Group < ActiveRecord::Base
2
+
3
+ has_many :accounts
4
+
5
+ has_many :images, as: :viewable
6
+ end
@@ -0,0 +1,11 @@
1
+ class Image < ActiveRecord::Base
2
+ include Cacheable
3
+
4
+ belongs_to :viewable, :polymorphic => true
5
+
6
+ after_commit :do_something
7
+
8
+ def do_something
9
+ e = 1337
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ class Location < ActiveRecord::Base
2
+
3
+ end
@@ -0,0 +1,31 @@
1
+ class Post < ActiveRecord::Base
2
+ include Cacheable
3
+
4
+ belongs_to :location
5
+ belongs_to :user
6
+
7
+ has_many :comments, :as => :commentable
8
+ has_many :images, :as => :viewable
9
+
10
+ has_and_belongs_to_many :tags
11
+
12
+ model_cache do
13
+ with_key
14
+ with_attribute :user_id
15
+ with_association :user, :comments, :images, :tags
16
+ with_class_method :default_post, :retrieve_with_user_id, :retrieve_with_both
17
+ end
18
+
19
+ def self.default_post
20
+ Post.first
21
+ end
22
+
23
+ def self.retrieve_with_user_id(user_id)
24
+ Post.find_by_user_id(user_id)
25
+ end
26
+
27
+ def self.retrieve_with_both(user_id, post_id)
28
+ Post.find(post_id) == Post.find_by_user_id(user_id)
29
+ end
30
+
31
+ end
@@ -0,0 +1,6 @@
1
+ class Tag < ActiveRecord::Base
2
+ include Cacheable
3
+
4
+ has_and_belongs_to_many :posts
5
+
6
+ end
@@ -0,0 +1,54 @@
1
+ class User < ActiveRecord::Base
2
+ include Cacheable
3
+
4
+ has_many :posts
5
+ has_one :account
6
+ has_many :images, through: :posts
7
+
8
+ has_one :group, through: :account
9
+
10
+ model_cache do
11
+ with_key
12
+ with_attribute :login
13
+ with_method :last_post, :bad_iv_name!, :bad_iv_name?
14
+ with_association :posts, :account, :images, :group
15
+ with_class_method :default_name, :user_with_id, :user_with_email,
16
+ :users_with_ids, :users_with_ids_in, :user_with_attributes
17
+ end
18
+
19
+ def last_post
20
+ posts.last
21
+ end
22
+
23
+ def self.default_name
24
+ "flyerhzm"
25
+ end
26
+
27
+ def bad_iv_name!
28
+ 42
29
+ end
30
+
31
+ def bad_iv_name?
32
+ 44
33
+ end
34
+
35
+ # accepts a number
36
+ def self.user_with_id(id)
37
+ User.find(id)
38
+ end
39
+
40
+ # accepts a string
41
+ def self.user_with_email(email)
42
+ User.find_by_email(email)
43
+ end
44
+
45
+ # accepts an array
46
+ def self.users_with_ids(ids)
47
+ User.find(ids)
48
+ end
49
+
50
+ # accepts a range
51
+ def self.users_with_ids_in(range)
52
+ User.select { |u| range.include?(u.id) }
53
+ end
54
+ end
@@ -0,0 +1,96 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
3
+
4
+ require 'rails'
5
+ require 'active_record'
6
+ require 'rspec'
7
+ require 'mocha/api'
8
+ require 'memcached'
9
+ require 'cacheable'
10
+
11
+ # It needs this order otherwise cacheable throws
12
+ # errors when looking for reflection classes
13
+ # Specifically, post can't be before tag
14
+ # and user can't be before post
15
+ require 'models/location'
16
+ require 'models/account'
17
+ require 'models/group'
18
+ require 'models/comment'
19
+ require 'models/image'
20
+ require 'models/tag'
21
+ require 'models/post'
22
+ require 'models/user'
23
+ require 'models/descendant'
24
+
25
+ ActiveRecord::Migration.verbose = false
26
+ ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ':memory:')
27
+
28
+ module Rails
29
+ class <<self
30
+ def cache
31
+ @cache ||= Memcached::Rails.new
32
+ end
33
+ end
34
+ end
35
+
36
+ RSpec.configure do |config|
37
+ config.mock_with :mocha
38
+
39
+ config.filter_run focus: true
40
+ config.run_all_when_everything_filtered = true
41
+
42
+ config.before :all do
43
+ ::ActiveRecord::Schema.define(:version => 1) do
44
+ create_table :users do |t|
45
+ t.string :login
46
+ t.string :email
47
+ end
48
+
49
+ create_table :accounts do |t|
50
+ t.integer :user_id
51
+ t.integer :group_id
52
+ end
53
+
54
+ create_table :posts do |t|
55
+ t.integer :user_id
56
+ t.string :title
57
+ t.integer :location_id
58
+ end
59
+
60
+ create_table :comments do |t|
61
+ t.integer :commentable_id
62
+ t.string :commentable_type
63
+ end
64
+
65
+ create_table :images do |t|
66
+ t.integer :viewable_id
67
+ t.string :viewable_type
68
+ t.string :name
69
+ end
70
+
71
+ create_table :tags do |t|
72
+ t.string :title
73
+ end
74
+
75
+ create_table :posts_tags, id: false do |t|
76
+ t.integer :post_id
77
+ t.integer :tag_id
78
+ end
79
+
80
+ create_table :groups do |t|
81
+ t.string :name
82
+ end
83
+
84
+ create_table :locations do |t|
85
+ t.string :city
86
+ end
87
+ end
88
+
89
+ end
90
+
91
+ config.after :all do
92
+ ::ActiveRecord::Base.connection.tables.each do |table|
93
+ ::ActiveRecord::Base.connection.drop_table(table)
94
+ end
95
+ end
96
+ end
metadata ADDED
@@ -0,0 +1,149 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: generation_cacheable
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Pat McGee
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-11-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 3.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: 3.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: '2.8'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: '2.8'
41
+ - !ruby/object:Gem::Dependency
42
+ name: mocha
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 0.10.5
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 0.10.5
55
+ description: a simple cache implementation with attribute based expiry
56
+ email:
57
+ - patmcgee331@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - .gitignore
63
+ - .rspec
64
+ - .ruby-gemset
65
+ - .ruby-version
66
+ - ChangeLog
67
+ - Gemfile
68
+ - README.md
69
+ - Rakefile
70
+ - generation_cacheable.gemspec
71
+ - lib/gen_cache.rb
72
+ - lib/gen_cache/cache_io/fetching.rb
73
+ - lib/gen_cache/cache_io/formatting.rb
74
+ - lib/gen_cache/cache_io/parsing.rb
75
+ - lib/gen_cache/cache_types/association_cache.rb
76
+ - lib/gen_cache/cache_types/attribute_cache.rb
77
+ - lib/gen_cache/cache_types/class_method_cache.rb
78
+ - lib/gen_cache/cache_types/key_cache.rb
79
+ - lib/gen_cache/cache_types/method_cache.rb
80
+ - lib/gen_cache/caches.rb
81
+ - lib/gen_cache/expiry.rb
82
+ - lib/gen_cache/keys.rb
83
+ - lib/gen_cache/version.rb
84
+ - spec/gen_cache/cache_io/fetching_spec.rb
85
+ - spec/gen_cache/cache_io/formatting_spec.rb
86
+ - spec/gen_cache/cache_io/parsing_spec.rb
87
+ - spec/gen_cache/cache_types/association_cache_spec.rb
88
+ - spec/gen_cache/cache_types/attribute_cache_spec.rb
89
+ - spec/gen_cache/cache_types/class_method_cache_spec.rb
90
+ - spec/gen_cache/cache_types/key_cache_spec.rb
91
+ - spec/gen_cache/cache_types/method_cache_spec.rb
92
+ - spec/gen_cache/expiry_spec.rb
93
+ - spec/gen_cache/keys_spec.rb
94
+ - spec/gen_cache_spec.rb
95
+ - spec/models/account.rb
96
+ - spec/models/comment.rb
97
+ - spec/models/descendant.rb
98
+ - spec/models/group.rb
99
+ - spec/models/image.rb
100
+ - spec/models/location.rb
101
+ - spec/models/post.rb
102
+ - spec/models/tag.rb
103
+ - spec/models/user.rb
104
+ - spec/spec_helper.rb
105
+ homepage: https://github.com/pathouse/generation-cacheable
106
+ licenses: []
107
+ metadata: {}
108
+ post_install_message:
109
+ rdoc_options: []
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - '>='
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - '>='
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ requirements: []
123
+ rubyforge_project:
124
+ rubygems_version: 2.0.3
125
+ signing_key:
126
+ specification_version: 4
127
+ summary: a simple cache implementation with attribute based expiry
128
+ test_files:
129
+ - spec/gen_cache/cache_io/fetching_spec.rb
130
+ - spec/gen_cache/cache_io/formatting_spec.rb
131
+ - spec/gen_cache/cache_io/parsing_spec.rb
132
+ - spec/gen_cache/cache_types/association_cache_spec.rb
133
+ - spec/gen_cache/cache_types/attribute_cache_spec.rb
134
+ - spec/gen_cache/cache_types/class_method_cache_spec.rb
135
+ - spec/gen_cache/cache_types/key_cache_spec.rb
136
+ - spec/gen_cache/cache_types/method_cache_spec.rb
137
+ - spec/gen_cache/expiry_spec.rb
138
+ - spec/gen_cache/keys_spec.rb
139
+ - spec/gen_cache_spec.rb
140
+ - spec/models/account.rb
141
+ - spec/models/comment.rb
142
+ - spec/models/descendant.rb
143
+ - spec/models/group.rb
144
+ - spec/models/image.rb
145
+ - spec/models/location.rb
146
+ - spec/models/post.rb
147
+ - spec/models/tag.rb
148
+ - spec/models/user.rb
149
+ - spec/spec_helper.rb