Permalink
Browse files

major refactoring and initial specs and README

  • Loading branch information...
1 parent a29e61c commit 18714d580f9ef9d50c6d153f35fd13440e8bd4ec @kristianmandrup committed Aug 12, 2012
Showing with 837 additions and 377 deletions.
  1. +6 −9 Gemfile
  2. +126 −0 Gemfile.lock
  3. +64 −0 README.md
  4. +0 −19 README.rdoc
  5. +2 −2 Rakefile
  6. +13 −0 lib/cantango-cache.rb
  7. +33 −74 lib/cantango/ability/cache/key.rb
  8. +29 −0 lib/cantango/ability/cache/keys/compare.rb
  9. +46 −0 lib/cantango/ability/cache/keys/permissions_key.rb
  10. +35 −0 lib/cantango/ability/cache/keys/roles_key.rb
  11. +20 −0 lib/cantango/ability/cache/keys/user.rb
  12. +1 −1 lib/cantango/ability/cache/reader.rb
  13. +1 −1 lib/cantango/ability/cache/writer.rb
  14. +1 −2 lib/cantango/ability/cached.rb
  15. +29 −0 lib/cantango/ability/executor/cache_mode.rb
  16. +5 −1 lib/cantango/ability/helper/cache.rb
  17. +1 −1 lib/cantango/ability_cache.rb
  18. +5 −0 lib/cantango/cache-ext.rb
  19. +1 −1 lib/cantango/cache.rb
  20. +7 −0 lib/cantango/cache/ability.rb
  21. +42 −0 lib/cantango/cache/ability/base_adapter.rb
  22. +5 −6 lib/cantango/cache/{moneta.rb → ability/moneta_adapter.rb}
  23. +45 −0 lib/cantango/cache/ability/session_adapter.rb
  24. +0 −24 lib/cantango/cache/base.rb
  25. +0 −44 lib/cantango/cache/session.rb
  26. +7 −0 lib/cantango/cache/stores.rb
  27. +36 −0 lib/cantango/cache/stores/base_store.rb
  28. +38 −0 lib/cantango/cache/stores/hash_store.rb
  29. +70 −0 lib/cantango/cache/stores/moneta_store.rb
  30. +7 −0 lib/cantango/cache_ext/executor.rb
  31. +21 −0 lib/cantango/cache_ext/executor/permit_type.rb
  32. +25 −17 lib/cantango/configuration/cache.rb
  33. +9 −0 lib/cantango/configuration/cache/Storage.rb
  34. +0 −32 lib/cantango/rules_cache.rb
  35. +0 −37 lib/cantango/rules_cache/hash_cache.rb
  36. +0 −68 lib/cantango/rules_cache/moneta_cache.rb
  37. 0 spec/cantango/{ → ability}/cache/key_spec.rb
  38. 0 spec/cantango/{ → ability}/cache/kompiler_spec.rb
  39. 0 spec/cantango/{ → ability}/cache/reader_compile_spec.rb
  40. 0 spec/cantango/{ → ability}/cache/reader_spec.rb
  41. 0 spec/cantango/{ → ability}/cache/writer_spec.rb
  42. 0 spec/cantango/{ → ability}/cache_spec.rb
  43. 0 spec/cantango/ability/helper/cache_spec.rb
  44. +1 −0 spec/cantango/cache/ability/base_adapter_spec.rb
  45. +1 −12 spec/cantango/cache/{moneta_spec.rb → ability/moneta_adapter_spec.rb}
  46. +10 −0 spec/cantango/cache/ability/session_adapter_spec.rb
  47. +12 −0 spec/cantango/cache/ability/shared_ex/moneta_ex.rb
  48. +0 −15 spec/cantango/cache/rules_cache_spec.rb
  49. +0 −11 spec/cantango/cache/session_cache_spec.rb
  50. +6 −0 spec/cantango/cache/stores/base_store_spec.rb
  51. +6 −0 spec/cantango/cache/stores/hash_store_spec.rb
  52. +6 −0 spec/cantango/cache/stores/moneta_store_spec.rb
  53. +28 −0 spec/cantango/configuration/cache_spec.rb
  54. +37 −0 spec/cantango/executor/permit_type_spec.rb
View
15 Gemfile
@@ -1,13 +1,10 @@
source "http://rubygems.org"
-# Add dependencies required to use your gem here.
-# Example:
-# gem "activesupport", ">= 2.3.5"
-# Add dependencies to develop your gem here.
-# Include everything needed to run rake, tests, features, etc.
+gem 'cantango-config'
+
group :development do
- gem "shoulda", ">= 0"
- gem "bundler", "~> 1.0.0"
- gem "jeweler", "~> 1.6.4"
- gem "rcov", ">= 0"
+ gem "rspec", ">= 2.8"
+ gem "bundler", ">= 1.1.0"
+ gem "jeweler", ">= 1.8.4"
+ gem "simplecov", ">= 0.5"
end
View
126 Gemfile.lock
@@ -0,0 +1,126 @@
+GEM
+ remote: http://rubygems.org/
+ specs:
+ actionmailer (3.2.8)
+ actionpack (= 3.2.8)
+ mail (~> 2.4.4)
+ actionpack (3.2.8)
+ activemodel (= 3.2.8)
+ activesupport (= 3.2.8)
+ builder (~> 3.0.0)
+ erubis (~> 2.7.0)
+ journey (~> 1.0.4)
+ rack (~> 1.4.0)
+ rack-cache (~> 1.2)
+ rack-test (~> 0.6.1)
+ sprockets (~> 2.1.3)
+ activemodel (3.2.8)
+ activesupport (= 3.2.8)
+ builder (~> 3.0.0)
+ activerecord (3.2.8)
+ activemodel (= 3.2.8)
+ activesupport (= 3.2.8)
+ arel (~> 3.0.2)
+ tzinfo (~> 0.3.29)
+ activeresource (3.2.8)
+ activemodel (= 3.2.8)
+ activesupport (= 3.2.8)
+ activesupport (3.2.8)
+ i18n (~> 0.6)
+ multi_json (~> 1.0)
+ arel (3.0.2)
+ builder (3.0.0)
+ cancan (1.6.8)
+ cantango-config (0.2.1)
+ cantango-core (~> 0.1.9)
+ hashie (~> 1.2)
+ rails (>= 3.1)
+ sugar-high (>= 0.6.1)
+ sweetloader (~> 0.1.6)
+ cantango-core (0.1.9.3)
+ cancan (>= 1.4)
+ hashie (~> 1.2)
+ rails (>= 3.0.1)
+ sugar-high (>= 0.6.0)
+ sweetloader (~> 0.1.5)
+ diff-lcs (1.1.3)
+ erubis (2.7.0)
+ git (1.2.5)
+ hashie (1.2.0)
+ hike (1.2.1)
+ i18n (0.6.0)
+ jeweler (1.8.4)
+ bundler (~> 1.0)
+ git (>= 1.2.5)
+ rake
+ rdoc
+ journey (1.0.4)
+ json (1.7.4)
+ mail (2.4.4)
+ i18n (>= 0.4.0)
+ mime-types (~> 1.16)
+ treetop (~> 1.4.8)
+ mime-types (1.19)
+ multi_json (1.3.6)
+ polyglot (0.3.3)
+ rack (1.4.1)
+ rack-cache (1.2)
+ rack (>= 0.4)
+ rack-ssl (1.3.2)
+ rack
+ rack-test (0.6.1)
+ rack (>= 1.0)
+ rails (3.2.8)
+ actionmailer (= 3.2.8)
+ actionpack (= 3.2.8)
+ activerecord (= 3.2.8)
+ activeresource (= 3.2.8)
+ activesupport (= 3.2.8)
+ bundler (~> 1.0)
+ railties (= 3.2.8)
+ railties (3.2.8)
+ actionpack (= 3.2.8)
+ activesupport (= 3.2.8)
+ rack-ssl (~> 1.3.2)
+ rake (>= 0.8.7)
+ rdoc (~> 3.4)
+ thor (>= 0.14.6, < 2.0)
+ rake (0.9.2.2)
+ rdoc (3.12)
+ json (~> 1.4)
+ rspec (2.11.0)
+ rspec-core (~> 2.11.0)
+ rspec-expectations (~> 2.11.0)
+ rspec-mocks (~> 2.11.0)
+ rspec-core (2.11.1)
+ rspec-expectations (2.11.2)
+ diff-lcs (~> 1.1.3)
+ rspec-mocks (2.11.2)
+ simplecov (0.6.4)
+ multi_json (~> 1.0)
+ simplecov-html (~> 0.5.3)
+ simplecov-html (0.5.3)
+ sprockets (2.1.3)
+ hike (~> 1.2)
+ rack (~> 1.0)
+ tilt (~> 1.1, != 1.3.0)
+ sugar-high (0.7.0)
+ sweetloader (0.1.6)
+ activesupport (>= 3.0.1)
+ i18n
+ thor (0.15.4)
+ tilt (1.3.3)
+ treetop (1.4.10)
+ polyglot
+ polyglot (>= 0.3.1)
+ tzinfo (0.3.33)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ bundler (>= 1.1.0)
+ cantango-config
+ jeweler (>= 1.8.4)
+ rspec (>= 2.8)
+ simplecov (>= 0.5)
View
64 README.md
@@ -0,0 +1,64 @@
+# Cantango cache
+
+The CanTango caching gem is designed to enable caching functionality for CanTango.
+
+To use it simply add it to your gemfile:
+
+`gem 'cantango-cache'`
+
+And then configure which cache and storage implementations you want to use and respective cache/storage options.
+
+```ruby
+
+CanTango.config.cache do |cache|
+ cache.type :session
+ cache.store do |store|
+ store.type :memory
+ # ...
+ end
+end
+```
+
+See specs for more info on how to configure.
+
+## Cache adapters
+
+The Cache system is based on Adapters that each subclass the BaseAdapter that defined the Adapter API. A cache can be configured with a storage module.
+
+The current Cache Adapter implementations are:
+
+* Moneta
+* Session
+
+The Session should be able to store the Ability in-memory or in any Session store that implements the Rails Session API, typically any key-value compatible data store.
+
+## Store
+
+A Store has the responsibility of storing an ability as a Hash in a data storage and later re-loading the hash as an Ability.
+
+The current Store implementations are:
+
+* Hash
+* Moneta
+
+Moneta is a wrapper for various key-value compatible data stores.
+
+## Status
+
+This gem is still under development and more specs are needed. The initial structure is mostly in place. The objective is to more strictly follow the Single Responsivility pattern and in general a more OO approach to make it easier to test and extend functionality and reduce coupling etc.
+
+## Contributing to cantango-cache
+
+* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
+* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
+* Fork the project
+* Start a feature/bugfix branch
+* Commit and push until you are happy with your contribution
+* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
+* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
+
+== Copyright
+
+Copyright (c) 2011 Kristian Mandrup. See LICENSE.txt for
+further details.
+
View
19 README.rdoc
@@ -1,19 +0,0 @@
-= cantango-cache
-
-Description goes here.
-
-== Contributing to cantango-cache
-
-* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
-* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
-* Fork the project
-* Start a feature/bugfix branch
-* Commit and push until you are happy with your contribution
-* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
-* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
-
-== Copyright
-
-Copyright (c) 2011 Kristian Mandrup. See LICENSE.txt for
-further details.
-
View
4 Rakefile
@@ -17,8 +17,8 @@ Jeweler::Tasks.new do |gem|
gem.name = "cantango-cache"
gem.homepage = "http://github.com/kristianmandrup/cantango-cache"
gem.license = "MIT"
- gem.summary = %Q{TODO: one-line summary of your gem}
- gem.description = %Q{TODO: longer description of your gem}
+ gem.summary = %Q{Caching for CanTango}
+ gem.description = %Q{Allow caching of CanTango Abilities}
gem.email = "kmandrup@gmail.com"
gem.authors = ["Kristian Mandrup"]
# dependencies defined in Gemfile
View
13 lib/cantango-cache.rb
@@ -0,0 +1,13 @@
+require 'cantango/cache_ext'
+
+module CanTango
+ module Ability
+ sweetload :Cache
+ end
+
+ module Configuration
+ sweetload :Cache
+ end
+
+ sweetload :Cache
+end
View
107 lib/cantango/ability/cache/key.rb
@@ -1,86 +1,45 @@
-module CanTango
- module Ability
- module Cache
- class Key
- attr_reader :user, :subject
+module CanTango::Ability::Cache
+ class Key
+ sweetload :UserKey, :PermissionsKey, :RolesKey, :Compare
- def initialize user, subject = nil, method_names = nil
- @user = user
- @subject = subject || user
- @method_names = method_names if method_names
- end
+ include CanTango::Ability:Cache::Keys::Compare
- def method_names
- @method_names ||= [:roles_list, :role_groups_list]
- end
+ attr_reader :user, :subject, :user_key, :permissions_key, :roles_key, :keys
- def self.create_for ability
- self.new ability.user, ability.subject
- end
-
- def value
- raise "No key could be generated for User:#{user.inspect} and Subject:#{subject} - key field: #{user_key_field}" if hash_values.empty?
- @value ||= hash_values.hash
- end
-
- def same? session
- raise "No session available" if !session
- session[:cache_key] && (value == session[:cache_key].value)
- end
-
- def to_s
- "key hash: #{value}"
- end
-
- protected
-
- def hash_values
- @hash_values ||= [user_key, subject_roles_hash, permissions_key].compact
- end
-
- def permissions_key
- return subject.send(:permissions_hash) if permissions_key? && subject.respond_to?(:permissions_hash)
- subject.send(:permissions) if permissions_key?
- end
-
- def permissions_key?
- subject.respond_to?(:permissions) && permission_engine.modes.include?(:cache) && permission_engine.on?
- end
-
- def user_key
- # raise "#{user.class} must have a method ##{user_key_field}. You can configure this with CanTango.config#user.unique_key_field" if !user.respond_to?(user_key_field)
- user.send(user_key_field) if user.respond_to? user_key_field
- end
-
- def user_key_field
- CanTango.config.user.unique_key_field || :email
- end
+ def initialize user, subject = nil, options = {}
+ @user = user
+ @subject = subject || user
+ configure_keys
+ end
- def subject_roles_hash
- role_hash_values.empty? ? nil : role_hash_values.hash
- end
+ class << self
+ def create_for ability
+ self.new ability.user, ability.subject
+ end
- def role_hash_values
- @role_hash_values ||= method_names.inject([]) do |result, meth_name|
- result << subject.send(meth_name) if use_in_hash? meth_name
- result
- end
- end
+ def configure_keys
+ @keys = options[:keys] if options[:keys] # allow override of keys to be used
- private
+ create_user_key user, options if key? :user
+ create_permissions_key subject, options if key? :permisssions
+ create_roles_key subject, options if key? :roles
+ end
- def permission_engine
- CanTango.config.engine(:user_ac)
- end
+ def create_user_key user
+ @user_key = CanTango::AbilityCache::Keys::UserKey.new user
+ end
- def use_in_hash? meth_name
- subject.respond_to?(meth_name) && CanTango.config.permits.enabled_types.include?(meth_map[meth_name])
- end
+ def create_permissions_key subject
+ @permissions_key = CanTango::AbilityCache::Keys::PermissionsKey.new subject
+ end
- def meth_map
- {:roles_list => :role, :role_groups_list => :role_group }
- end
+ def create_roles_key subject
+ @roles_key = CanTango::AbilityCache::Keys::RolesKey.new subject
end
end
+
+ def to_s
+ "key hash: #{value}"
+ end
end
-end
+end
View
29 lib/cantango/ability/cache/keys/compare.rb
@@ -0,0 +1,29 @@
+module CanTango::Ability::Cache
+ module Keys
+ module Compare
+ def same? session
+ raise "No session available" if !session
+ session[:cache_key] && (value == session[:cache_key].value)
+ end
+
+ def value
+ raise "No key could be generated for User:#{user.inspect} and Subject:#{subject} - key field: #{user_key_field}" if hash_values.empty?
+ @value ||= values.hash
+ end
+
+ def keys
+ @keys ||= %w{user permissions roles}
+ end
+
+ def key? name
+ keys.map(&:to_sym).include? name.to_sym
+ end
+
+ protected
+
+ def values
+ @values ||= keys.select {|key| send("#{key}_key").value }
+ end
+ end
+ end
+end
View
46 lib/cantango/ability/cache/keys/permissions_key.rb
@@ -0,0 +1,46 @@
+module CanTango::Ability::Cache
+ module Keys
+ class PermissionsKey
+ attr_reader :subject
+
+ def initialize subject
+ @subject = subject
+ end
+
+ def cache_key
+ return permissions_hash if cache_key? && has_permissions?
+ permissions if cache_key?
+ end
+
+ def cache_key?
+ permissions? && permission_cache_on?
+ end
+
+ protected
+
+ def modes
+ engine(:permit).modes
+ end
+
+ def permissions_hash
+ subject.send(:permissions_hash)
+ end
+
+ def permissions
+ subject.send(:permissions)
+ end
+
+ def permission_cache_on?
+ modes.include?(:cache) && engine(:permission).on?
+ end
+
+ def permissions_hash?
+ subject.respond_to?(:permissions_hash)
+ end
+
+ def permissions?
+ subject.respond_to?(:permissions)
+ end
+ end
+ end
+end
View
35 lib/cantango/ability/cache/keys/roles_key.rb
@@ -0,0 +1,35 @@
+module CanTango::Ability::Cache
+ module Keys
+ class RolesKey
+ attr_reader :subject
+
+ def initialize subject, options = {}
+ @subject = subject
+ @method_names = options[:methods] if options[:methods]
+ end
+
+ def method_names
+ @method_names ||= [:roles_list, :role_groups_list]
+ end
+
+ def value
+ hash_values.empty? ? nil : hash_values.hash
+ end
+
+ def hash_values
+ @hash_values ||= method_names.inject([]) do |result, meth_name|
+ result << subject.send(meth_name) if use_in_hash? meth_name
+ result
+ end
+ end
+
+ def meth_map
+ {:roles_list => :role, :role_groups_list => :role_group }
+ end
+
+ def use_in_hash? meth_name
+ subject.respond_to?(meth_name) && CanTango.config.permits.enabled_types.include?(meth_map[meth_name])
+ end
+ end
+ end
+end
View
20 lib/cantango/ability/cache/keys/user.rb
@@ -0,0 +1,20 @@
+module CanTango::Ability::Cache
+ module Keys
+ class UserKey
+ attr_reader :user
+
+ def initialize user
+ @user = user
+ end
+
+ def user_key
+ # raise "#{user.class} must have a method ##{user_key_field}. You can configure this with CanTango.config#user.unique_key_field" if !user.respond_to?(user_key_field)
+ user.send(user_key_field) if user.respond_to? user_key_field
+ end
+
+ def user_key_field
+ CanTango.config.user.unique_key_field || :email
+ end
+ end
+ end
+end
View
2 lib/cantango/ability/cache/reader.rb
@@ -2,7 +2,7 @@ module CanTango
module Ability
module Cache
class Reader
- include CanTango::Helpers::Debug
+ include CanTango::Helper::Debug
attr_reader :cache
View
2 lib/cantango/ability/cache/writer.rb
@@ -2,7 +2,7 @@ module CanTango
module Ability
module Cache
class Writer
- include CanTango::Helpers::Debug
+ include CanTango::Helper::Debug
attr_reader :cache, :cache_key
View
3 lib/cantango/ability/cached.rb
@@ -25,5 +25,4 @@ def permit_rules
end
end
end
-
-end
+end
View
29 lib/cantango/ability/executor/cache_mode.rb
@@ -0,0 +1,29 @@
+module CanTango
+ class Ability
+ module Executor
+ class CachedMode < Base
+ include CanTango::Ability::Helper::Cache
+
+ # FIX! no reason for double cache check!
+ def cached?
+ @rules = cached_rules if cached_rules? && caching_on?
+ end
+
+ def cache
+ @cache ||= cache_class.new self, :cache_key => cache_key, :key_method_names => key_method_names
+ end
+
+ protected
+
+ def start_execute
+ debug "Executing cached ability"
+ end
+
+ def end_execute
+ cache_rules! if caching_on?
+ debug "DONE"
+ end
+ end
+ end
+ end
+end
View
6 lib/cantango/ability/helper/cache.rb
@@ -7,8 +7,12 @@ module Cache
delegate :cache_rules!, :cached_rules, :cached_rules?, :to => :cache
def cache options = {}
- @cache ||= CanTango::Ability::Cache.new self, options
+ @cache ||= cache_class.new self, options
end
+
+ def cache_class
+ CanTango::Ability::Cached
+ end
end
end
end
View
2 lib/cantango/ability_cache.rb
@@ -1,7 +1,7 @@
module CanTango
module Ability
class Cache
- autoload_modules :BaseCache, :SessionCache, :Reader, :Writer, :RulesCache, :Key
+ sweetload :BaseCache, :SessionCache, :Reader, :Writer, :RulesCache, :Key
include CanTango::Helpers::Debug
include CanTango::Helpers::RoleMethods
View
5 lib/cantango/cache-ext.rb
@@ -0,0 +1,5 @@
+module CanTango
+ sweet_scope :ns => {:CanTango => 'cantango/cache_ext'} do
+ sweetload :Executor
+ end
+end
View
2 lib/cantango/cache.rb
@@ -1,5 +1,5 @@
module CanTango
module Cache
- autoload_modules :Base, :Moneta, :Session
+ sweetload :Base, :Moneta, :Session
end
end
View
7 lib/cantango/cache/ability.rb
@@ -0,0 +1,7 @@
+module CanTango
+ module Cache
+ module Ability
+ sweetload :BaseAdapter, :MonetaAdapter, :SessionAdapter
+ end
+ end
+end
View
42 lib/cantango/cache/ability/base_adapter.rb
@@ -0,0 +1,42 @@
+module CanTango
+ module Cache
+ module Ability
+ # basic functionality for Caching a CanTango ability in a store
+ class BaseAdapter
+ attr_reader :name, :options, :store
+
+ # name of store and options to initialize it with!
+ def initialize name, options = {}
+ @name, @options = [name, options]
+ configure_options
+ configure_store options[:store_class]
+ end
+
+ def self.configure_options
+ options.each_pair do |name, value|
+ var = :"@#{name}"
+ self.instance_variable_set(var, value)
+ end
+ end
+
+ # configure the store used, fx Moneta or Hash store
+ def self.configure_store store_clazz
+ @store = (store_clazz || default_store_class).instance
+ @store.configure_with options
+ end
+
+ def default_store_class
+ raise NotImplementedError
+ end
+
+ def load key
+ raise NotImplementedError
+ end
+
+ def save key, rules
+ raise NotImplementedError
+ end
+ end
+ end
+ end
+end
View
11 lib/cantango/cache/moneta.rb → lib/cantango/cache/ability/moneta_adapter.rb
@@ -3,15 +3,14 @@
module CanTango
module Cache
- class Moneta < Base
- # one cache store is shared for all store instances (w different names)
- attr_reader :store
-
+ class MonetaAdapter < BaseAdapter
# for a YamlStore, the name is the name of the yml file
def initialize name, options = {}
super
- @store = CanTango::Cache::MonetaCache.instance
- @store.configure_with options
+ end
+
+ def self.default_store_class
+ CanTango::Cache::Store::MonetaAdapter
end
def load key
View
45 lib/cantango/cache/ability/session_adapter.rb
@@ -0,0 +1,45 @@
+module CanTango
+ module Cache
+ module Adapter
+ class Session < Base
+ attr_accessor :session
+ attr_reader :key
+
+ # will be called with :session => session (pointing to user session)
+ def initialize name, options = {}
+ super # will set all instance vars using options hash
+
+ raise "SessionCache must be initialized with a :session option" if !session
+ session[cache_key] = @cache
+ end
+
+ def self.default_store_class
+ CanTango::Cache::Store::HashAdapter
+ end
+
+ def store
+ session[cache_key]
+ end
+
+ def cache_key
+ @cache_key ||= :rules_cache
+ end
+
+ def load key
+ raise "no key" if key.nil?
+ store.load! key
+ end
+
+ def save key, rules
+ raise "no key" if key.nil?
+ store.save!(key, rules)
+ end
+
+ def invalidate! key
+ raise "no key" if key.nil?
+ store.delete(key)
+ end
+ end
+ end
+ end
+end
View
24 lib/cantango/cache/base.rb
@@ -1,24 +0,0 @@
-module CanTango
- module Cache
- class Base
- attr_reader :name, :options
-
- def initialize name, options = {}
- @name, @options = [name, options]
-
- options.each_pair do |name, value|
- var = :"@#{name}"
- self.instance_variable_set(var, value)
- end
- end
-
- def load key
- raise NotImplementedError
- end
-
- def save key, rules
- raise NotImplementedError
- end
- end
- end
-end
View
44 lib/cantango/cache/session.rb
@@ -1,44 +0,0 @@
-module CanTango
- module Cache
- class Session < Base
- attr_accessor :session
- attr_reader :key
-
- # will be called with :session => session (pointing to user session)
- def initialize name, options = {}
- super # will set all instance vars using options hash
- @cache = cache
- @cache.configure_with :type => :memory
- raise "SessionCache must be initialized with a :session option" if !session
- session[cache_key] = @cache
- end
-
- def cache_key
- @cache_key ||= :rules_cache
- end
-
- def store
- session[cache_key]
- end
-
- def load key
- raise "no key" if key.nil?
- store.load! key
- end
-
- def save key, rules
- raise "no key" if key.nil?
- store.save!(key, rules)
- end
-
- def invalidate! key
- raise "no key" if key.nil?
- store.delete(key)
- end
-
- def cache
- CanTango::Cache::HashCache.instance
- end
- end
- end
-end
View
7 lib/cantango/cache/stores.rb
@@ -0,0 +1,7 @@
+module CanTango
+ module Cache
+ module Stores
+ sweetload :BaseStore, :HashStore, :MonetaStore
+ end
+ end
+end
View
36 lib/cantango/cache/stores/base_store.rb
@@ -0,0 +1,36 @@
+module CanTango
+ module Cache
+ module Stores
+ class BaseStore
+ attr_reader :session
+
+ def instance
+ @instance ||= clazz.new :rules_cache, options
+ end
+
+ def initialize session = nil
+ @session = session
+ end
+
+ def options
+ @options ||= session ? cache_options.merge(:session => session) : cache_options
+ end
+
+ def cache_options
+ cache_engine.store.options || {}
+ end
+
+ def clazz
+ cache_engine.store.default_class
+ end
+
+ protected
+
+ def cache_engine
+ raise "Cache engine not registered!" if !CanTango.config.engine(:cache)
+ CanTango.config.engine(:cache)
+ end
+ end
+ end
+ end
+end
View
38 lib/cantango/cache/stores/hash_store.rb
@@ -0,0 +1,38 @@
+module CanTango
+ module Cache
+ module Stores
+ class HashStore < BaseStore
+ include Singleton
+
+ attr_reader :options
+
+ def configure_with options = {}
+ @options ||= options
+ end
+
+ def load! key
+ raise "no key" if key.nil?
+ cache[key]
+ end
+
+ def save! key, rules
+ raise "no key" if key.nil?
+ cache[key] = rules
+ end
+
+ def delete key
+ raise "no key" if key.nil?
+ cache[key].delete if cache[key]
+ end
+
+ def cache
+ @cache ||= {}
+ end
+
+ def type
+ :memory
+ end
+ end
+ end
+ end
+end
View
70 lib/cantango/cache/stores/moneta_store.rb
@@ -0,0 +1,70 @@
+module CanTango
+ module Cache
+ module Stores
+ class MonetaStore < BaseStore
+ include Singleton
+
+ attr_reader :options
+
+ def configure_with options = {}
+ @options ||= options
+ @type ||= options[:type] || CanTango.config.cache.store.default_type
+ end
+
+ def load! key
+ cache[key]
+ end
+
+ def save! key, rules
+ cache.store key, rules
+ end
+
+ def delete key
+ cache.delete key
+ end
+
+ def cache
+ @cache ||= begin
+ moneta = eval(factory_statement)
+ moneta.clear
+ moneta
+ end
+ end
+
+ def factory_statement
+ %{
+ ::Moneta::Builder.build do
+ #{run_adapter}
+ end
+ }
+ end
+
+ def run_adapter
+ case type.to_sym
+ when :yaml
+ yaml_adapter
+ else
+ simple_adapter
+ end
+ end
+
+ def yaml_adapter
+ "run #{adapter}, #{options}"
+ end
+
+ def simple_adapter
+ "run #{adapter}"
+ end
+
+ def type
+ (@type == :yaml) ? :YAML : @type
+ end
+
+ def adapter
+ require "moneta/adapters/#{type}"
+ @adapter = "Moneta::Adapters::#{type.to_s.camelize}".constantize
+ end
+ end
+ end
+ end
+end
View
7 lib/cantango/cache_ext/executor.rb
@@ -0,0 +1,7 @@
+module CanTango
+ sweet_scope :ns => {:CanTango => 'cantango/cache_ext'} do
+ module Executor
+ sweetload :PermitType
+ end
+ end
+end
View
21 lib/cantango/cache_ext/executor/permit_type.rb
@@ -0,0 +1,21 @@
+module CanTango
+ module Executor
+ class PermitType < Base
+ attr_writer :ability_cache_clazz
+
+ alias_method :cache_key, :permit_type
+
+ def cache
+ @cache ||= ability_cache_clazz.new self, cache_options
+ end
+
+ def cache_options
+ {:cache_key => cache_key, :key_method_names => key_method_names}
+ end
+
+ def ability_cache_clazz
+ @ability_cache_clazz ||= CanTango::Ability::Cache
+ end
+ end
+ end
+end
View
42 lib/cantango/configuration/cache.rb
@@ -1,25 +1,33 @@
module CanTango
class Configuration
- class Engines
- class Cache < Engine
+ class Cache
+ sweetload :Storage
- def compile state
- raise "Must be set to :on or :off" if ![:on, :off].include? state
- @compile = state
- end
+ def compile state
+ raise "Must be set to :on or :off" if ![:on, :off].include? state
+ @compile = state
+ end
+
+ def compile?
+ @compile ||= :on
+ @compile == :on
+ end
- def compile?
- @compile ||= :on
- @compile == :on
- end
+ # yield a store configuration object
+ def store options = {}, &block
+ @store ||= store_clazz.new
+ @store.adapter_class ||= default_adapter_class
+ @store.default_options = options
+ yield @store if block_given?
+ @store
+ end
+
+ def default_adapter_class
+ CanTango::Cache::Store::SessionAdapter
+ end
- def store &block
- @store ||= ns::Store.new
- # CanTango::Ability::Cache::MonetaCache
- @store.default_class ||= CanTango::Ability::Cache::SessionCache
- yield @store if block
- @store
- end
+ def store_clazz
+ ns::Storage
end
end
end
View
9 lib/cantango/configuration/cache/Storage.rb
@@ -0,0 +1,9 @@
+module CanTango
+ class Configuration
+ class Cache
+ # Storage configuration object
+ class Storage
+ end
+ end
+ end
+end
View
32 lib/cantango/rules_cache.rb
@@ -1,32 +0,0 @@
-module CanTango
- class RulesCache
- attr_reader :session
-
- def instance
- @instance ||= clazz.new :rules_cache, options
- end
-
- def initialize session = nil
- @session = session
- end
-
- def options
- @options ||= session ? cache_options.merge(:session => session) : cache_options
- end
-
- def cache_options
- cache_engine.store.options || {}
- end
-
- def clazz
- cache_engine.store.default_class
- end
-
- protected
-
- def cache_engine
- raise "Cache engine not registered!" if !CanTango.config.engine(:cache)
- CanTango.config.engine(:cache)
- end
- end
-end
View
37 lib/cantango/rules_cache/hash_cache.rb
@@ -1,37 +0,0 @@
-module CanTango
- module RulesCache
- class Hash
- include Singleton
-
- attr_reader :options
-
- def configure_with options = {}
- @options ||= options
- end
-
- def load! key
- raise "no key" if key.nil?
- cache[key]
- end
-
- def save! key, rules
- raise "no key" if key.nil?
- cache[key] = rules
- end
-
- def delete key
- raise "no key" if key.nil?
- cache[key].delete if cache[key]
- end
-
- def cache
- @cache ||= {}
- end
-
- def type
- :memory
- end
- end
- end
-end
-
View
68 lib/cantango/rules_cache/moneta_cache.rb
@@ -1,68 +0,0 @@
-module CanTango
- module RulesCache
- class MonetaCache
- include Singleton
-
- attr_reader :options
-
- def configure_with options = {}
- @options ||= options
- @type ||= options[:type] || CanTango.config.cache.store.default_type
- end
-
- def load! key
- cache[key]
- end
-
- def save! key, rules
- cache.store key, rules
- end
-
- def delete key
- cache.delete key
- end
-
- def cache
- @cache ||= begin
- moneta = eval(factory_statement)
- moneta.clear
- moneta
- end
- end
-
- def factory_statement
- %{
- ::Moneta::Builder.build do
- #{run_adapter}
- end
- }
- end
-
- def run_adapter
- case type.to_sym
- when :yaml
- yaml_adapter
- else
- simple_adapter
- end
- end
-
- def yaml_adapter
- "run #{adapter}, #{options}"
- end
-
- def simple_adapter
- "run #{adapter}"
- end
-
- def type
- (@type == :yaml) ? :YAML : @type
- end
-
- def adapter
- require "moneta/adapters/#{type}"
- @adapter = "Moneta::Adapters::#{type.to_s.camelize}".constantize
- end
- end
- end
-end
View
0 spec/cantango/cache/key_spec.rb → spec/cantango/ability/cache/key_spec.rb
File renamed without changes.
View
0 spec/cantango/cache/kompiler_spec.rb → spec/cantango/ability/cache/kompiler_spec.rb
File renamed without changes.
View
0 spec/cantango/cache/reader_compile_spec.rb → ...ango/ability/cache/reader_compile_spec.rb
File renamed without changes.
View
0 spec/cantango/cache/reader_spec.rb → spec/cantango/ability/cache/reader_spec.rb
File renamed without changes.
View
0 spec/cantango/cache/writer_spec.rb → spec/cantango/ability/cache/writer_spec.rb
File renamed without changes.
View
0 spec/cantango/cache_spec.rb → spec/cantango/ability/cache_spec.rb
File renamed without changes.
View
0 spec/cantango/ability/helper/cache_spec.rb
No changes.
View
1 spec/cantango/cache/ability/base_adapter_spec.rb
@@ -0,0 +1 @@
+require 'spec_helper'
View
13 spec/cantango/cache/moneta_spec.rb → ...ango/cache/ability/moneta_adapter_spec.rb
@@ -2,18 +2,7 @@
require "moneta/adapters/memory"
-shared_examples_for "a read/write Moneta cache" do
- types = {
- "String" => ["key", "key2"],
- "Object" => [{:foo => :bar}, {:bar => :baz}]
- }
-
- types.each do |type, (key, key2)|
- it "reads from keys that are #{type}s like a Hash" do
- @cache[key].should == nil
- end
- end
-end
+require "cantango/cache/ability/shared_ex/moneta_ex"
describe "Moneta::Adapters::Memory" do
#class EmptyMiddleware
View
10 spec/cantango/cache/ability/session_adapter_spec.rb
@@ -0,0 +1,10 @@
+require 'rspec'
+require 'cantango'
+
+describe CanTango::Cache::Ability::SessionAdapter do
+ subject { CanTango::Cache::Ability::SessionAdapter.new :roles, :session => {} }
+ its(:name) { should == :roles}
+ its(:store) { should_not be_nil}
+ its(:store) { should be_a CanTango::Cache::Stores::HashStore }
+end
+
View
12 spec/cantango/cache/ability/shared_ex/moneta_ex.rb
@@ -0,0 +1,12 @@
+shared_examples_for "a read/write Moneta cache" do
+ types = {
+ "String" => ["key", "key2"],
+ "Object" => [{:foo => :bar}, {:bar => :baz}]
+ }
+
+ types.each do |type, (key, key2)|
+ it "reads from keys that are #{type}s like a Hash" do
+ @cache[key].should == nil
+ end
+ end
+end
View
15 spec/cantango/cache/rules_cache_spec.rb
@@ -1,15 +0,0 @@
-require 'spec_helper'
-
-describe CanTango::Ability::Cache::RulesCache do
- let (:session) do
- {}
- end
-
- subject do
- CanTango::Ability::Cache::RulesCache.new session
- end
-
- specify { subject.should be_a CanTango::Ability::Cache::RulesCache }
-end
-
-
View
11 spec/cantango/cache/session_cache_spec.rb
@@ -1,11 +0,0 @@
-require 'rspec'
-require 'cantango'
-
-describe CanTango::Ability::Cache::SessionCache do
- subject { CanTango::Ability::Cache::SessionCache.new :roles, :session => {} }
- its(:name) { should == :roles}
- its(:store) { should_not be_nil}
- its(:store) { should be_a CanTango::Cache::HashCache }
-
-end
-
View
6 spec/cantango/cache/stores/base_store_spec.rb
@@ -0,0 +1,6 @@
+require 'spec_helper'
+
+describe CanTango::Cache::Stores::BaseStore do
+end
+
+
View
6 spec/cantango/cache/stores/hash_store_spec.rb
@@ -0,0 +1,6 @@
+require 'spec_helper'
+
+describe CanTango::Cache::Stores::HashStore do
+end
+
+
View
6 spec/cantango/cache/stores/moneta_store_spec.rb
@@ -0,0 +1,6 @@
+require 'spec_helper'
+
+describe CanTango::Cache::Stores::MonetaStore do
+end
+
+
View
28 spec/cantango/configuration/cache_spec.rb
@@ -0,0 +1,28 @@
+require 'spec_helper'
+
+describe CanTango::Configuration::Cache
+ subject { clazz }
+ let(:clazz) { CanTango::Configuration::Cache }
+
+ describe '.compile and compile?' do
+ specify { subject.compile(:on).compile?.should be_true }
+ specify { subject.compile(:off).compile?.should be_false }
+
+ expect { subject.compile(:unknown).to raise_error }
+ end
+
+ describe '.store' do
+ specify { subject.store.should be_a CanTango::Configuration::Cache::Storage }
+
+ it 'should allow configuration of caching' do
+ subject.store :type => :memory do |cache|
+ cache.adapter_class = CanTango::Cache::Store::MonetaAdapter
+ cache.options = {:host => 'localhost'}
+ end
+ end
+ end
+
+ describe '.store_clazz' do
+ specify { subject.store_clazz.should == CanTango::Configuration::Cache::Store }
+ end
+end
View
37 spec/cantango/executor/permit_type_spec.rb
@@ -0,0 +1,37 @@
+require 'spec_helper'
+
+class MyAbilityCache
+end
+
+describe CanTango::Executor::PermitType
+ context 'with cache' do
+ subject { CanTango::Executor::PermitType }
+
+ # set up cache_key alias
+ describe '.cache_key' do
+ its(:cache_key) { should == subject.permit_type }
+ end
+
+ describe '.ability_cache_clazz' do
+ its(:ability_cache_clazz) { should == CanTango::Ability::Cache }
+ end
+
+ describe '.cache' do
+ its(:cache) { should be_a CanTango::Ability::Cache }
+ end
+
+ context 'change ability class to MyAbilityCache' do
+ before do
+ subject.ability_cache_clazz = MyAbilityCache
+ end
+
+ describe '.ability_cache_clazz = ' do
+ its(:ability_cache_clazz) { should == MyAbilityCache }
+ end
+
+ describe '.cache' do
+ its(:cache) { should be_a MyAbilityCache }
+ end
+ end
+ end
+end

0 comments on commit 18714d5

Please sign in to comment.