The Sequel cache is a cache system that uses the Sequel database toolkit to store the data in a DBMS supported by Sequel. Examples of these databases are MySQL, SQLite3 and so on. In order to use this cache you’d have to do the following:
Ramaze::Cache.options.view = Ramaze::Cache::Sequel.using( :connection => Sequel.mysql( :host => 'localhost', :user => 'user', :password => 'password', :database => 'blog' ), :table => :blog_sessions )
If you already have an existing connection you can just pass the object to the :connection option instead of creating a new connection manually.
Massive thanks to Lars Olsson for patching the original Sequel cache so that it supports multiple connections and other useful features.
@example Setting a custom database connection
Ramaze::Cache.options.names.push(:sequel) Ramaze::Cache.options.sequel = Ramaze::Cache::Sequel.using( :connection => Sequel.connect( :adapter => 'mysql2', :host => 'localhost', :username => 'cache', :password => 'cache123', :database => 'ramaze_cache' ) )
@author Lars Olsson @since 18-04-2011
Creates a new instance of the cache class.
@author Michael Fellinger @since 04-05-2011 @param [Hash] options A hash with custom options, see
Ramaze::Cache::Sequel.using for all available options.
# File lib/ramaze/cache/sequel.rb, line 137 137: def initialize(options = {}) 138: self.class.options ||= Ramaze::Cache::Sequel.trait[:default].merge( 139: options 140: ) 141: 142: @options = options.merge(self.class.options) 143: end
This method returns a subclass of Ramaze::Cache::Sequel with the provided options set. This is necessary because Ramaze expects a class and not an instance of a class for its cache option.
You can provide any parameters you want, but those not used by the cache will not get stored. No parameters are mandatory. Any missing parameters will be replaced by default values.
@example
## # This will create a mysql session cache in the blog # database in the table blog_sessions # Please note that the permissions on the database must # be set up correctly before you can just create a new table # Ramaze.options.cache.session = Ramaze::Cache::Sequel.using( :connection => Sequel.mysql( :host =>'localhost', :user =>'user', :password =>'password', :database =>'blog' ), :table => :blog_sessions )
@author Lars Olsson @since 18-04-2011 @param [Object] options A hash containing the options to use @option options [Object] :connection a Sequel database object
(Sequel::Database) You can use any parameters that Sequel supports for this object. If this option is left unset, a Sqlite memory database will be used.
@option options [String] :table The table name you want to use for the
cache. Can be either a String or a Symbol. If this option is left unset, a table called ramaze_cache will be used.
@option options [Fixnum] :ttl Setting this value will override
Ramaze's default setting for when a particular cache item will be invalidated. By default this setting is not used and the cache uses the values provided by Ramaze, but if you want to use this setting it should be set to an integer representing the number of seconds before a cache item becomes invalidated.
@option options [TrueClass] :display_warnings When this option is set
to true, failure to serialiaze or deserialize cache items will produce a warning in the Ramaze log. This option is set to false by default. Please note that certain objects (for instance Procs) cannot be serialized by ruby and therefore cannot be cached by this cache class. Setting this option to true is a good way to find out if the stuff you are trying to cache is affected by this. Failure to serialize/deserialize a cache item will never raise an exception, the item will just remain uncached.
@return [Object]
# File lib/ramaze/cache/sequel.rb, line 123 123: def using(options = {}) 124: merged = Ramaze::Cache::Sequel.trait[:default].merge(options) 125: Class.new(self) { @options = merged } 126: end
Remove all key/value pairs from the cache. Should behave as if # had been called with all keys as argument.
@author Lars Olsson @since 18-04-2011
# File lib/ramaze/cache/sequel.rb, line 182 182: def cache_clear 183: @dataset.delete 184: end
Remove the corresponding key/value pair for each key passed. If removing is not an option it should set the corresponding value to nil.
If only one key was deleted, answer with the corresponding value. If multiple keys were deleted, answer with an Array containing the values.
@author Lars Olsson @since 18-04-2011 @param [Object] key The key for the value to delete @param [Object] keys Any other keys to delete as well @return [Object/Array/nil]
# File lib/ramaze/cache/sequel.rb, line 199 199: def cache_delete(key, *keys) 200: # Remove a single key 201: if keys.empty? 202: nkey = namespaced(key) 203: result = @dataset.select(:value).filter(:key => nkey).limit(1) 204: 205: # Ramaze expects nil values 206: if result.empty? 207: result = nil 208: else 209: result = deserialize(result.first[:value]) 210: end 211: 212: @dataset.filter(:key => nkey).delete 213: # Remove multiple keys 214: else 215: nkeys = [key, keys].flatten.map! { |nkey| namespaced(nkey) } 216: result = dataset.select(:value).filter(:key => nkeys) 217: 218: result.map! do |row| 219: deserialize(row[:value]) 220: end 221: 222: @dataset.filter(:key => nkeys).delete 223: end 224: 225: return result 226: end
Answer with the value associated with the key, nil if not found or expired.
@author Lars Olsson @since 18-04-2011 @param [Object] key The key for which to fetch the value @param [Object] default Will return this if no value was found @return [Object]
# File lib/ramaze/cache/sequel.rb, line 238 238: def cache_fetch(key, default = nil) 239: nkey = namespaced(key) 240: 241: # Delete expired rows 242: @dataset.select.filter(:key => nkey) do 243: expires < Time.now 244: end.delete 245: 246: # Get remaining row (if any) 247: result = @dataset.select(:value).filter(:key => nkey).limit(1) 248: 249: if result.empty? 250: return default 251: else 252: return deserialize(result.first[:value]) 253: end 254: end
Executed after # and before any other method.
Some parameters identifying the current process will be passed so caches that act in one global name-space can use them as a prefix.
@author Lars Olsson @since 18-04-2011 @param [String] hostname the hostname of the machine @param [String] username user executing the process @param [String] appname identifier for the application @param [String] cachename namespace, like ‘session’ or ‘action’
# File lib/ramaze/cache/sequel.rb, line 158 158: def cache_setup(hostname, username, appname, cachename) 159: @namespace = [hostname, username, appname, cachename].compact.join(':') 160: 161: # Create the table if it's not there yet 162: if !options[:connection].table_exists?(options[:table]) 163: options[:connection].create_table( 164: options[:table]) do 165: primary_key :id 166: String :key , :null => false, :unique => true 167: String :value, :text => true 168: Time :expires 169: end 170: end 171: 172: @dataset = options[:connection][options[:table].to_sym] 173: end
Sets the given key to the given value.
@example
Cache.value.store(:num, 3, :ttl => 20) Cache.value.fetch(:num)
@author Lars Olsson @since 18-04-2011 @param [Object] key The value is stored with this key @param [Object] value The key points to this value @param [Hash] options for now, only :ttl => Fixnum is used. @option options [Fixnum] :ttl The time in seconds after which the cache
item should be expired.
# File lib/ramaze/cache/sequel.rb, line 271 271: def cache_store(key, value, options = {}) 272: nkey = namespaced(key) 273: 274: # Get the time after which the cache should be expired 275: if options[:ttl] 276: ttl = options[:ttl] 277: else 278: ttl = Ramaze::Cache::Sequel.options[:ttl] 279: end 280: 281: expires = Time.now + ttl if ttl 282: 283: # The row already exists, update it. 284: if @dataset.filter(:key => nkey).count == 1 285: serialized_value = serialize(value) 286: 287: if serialized_value 288: @dataset.update(:value => serialize(value), :expires => expires) 289: end 290: # The row doesn't exist yet. 291: else 292: serialized_value = serialize(value) 293: 294: if serialized_value 295: @dataset.insert( 296: :key => nkey, :value => serialize(value), :expires => expires 297: ) 298: end 299: end 300: 301: # Try to deserialize the value. If this fails we'll return a different 302: # value 303: deserialized = deserialize(@dataset.select(:value) .filter(:key => nkey) .limit(1).first[:value]) 304: 305: if deserialized 306: return deserialized 307: else 308: return value 309: end 310: end
Deserialize method, adapted from Sequels serialize plugin This method will try to deserialize a value using Marshal.load
@author Lars Olsson @since 18-04-2011 @param [Object] value Value to be deserialized @return [Object nil]
# File lib/ramaze/cache/sequel.rb, line 335 335: def deserialize(value) 336: begin 337: ::Marshal.load(value.unpack('m')[0]) 338: rescue 339: begin 340: ::Marshal.load(value) 341: rescue 342: # Log the error? 343: if options[:display_warnings] === true 344: Ramaze::Log::warn("Failed to deserialize #{value.inspect}") 345: end 346: 347: return nil 348: end 349: end 350: end
Prefixes the given key with current namespace.
@author Lars Olsson @since 18-04-2011 @param [Object] key Key without namespace. @return [Object]
# File lib/ramaze/cache/sequel.rb, line 322 322: def namespaced(key) 323: return [@namespace, key].join(':') 324: end
Serialize method, adapted from Sequels serialize plugin This method will try to serialize a value using Marshal.dump
@author Lars Olsson @since 18-04-2011 @param [Object] value Value to be serialized. @return [Object nil]
# File lib/ramaze/cache/sequel.rb, line 361 361: def serialize(value) 362: begin 363: [::Marshal.dump(value)].pack('m') 364: rescue 365: if options[:display_warnings] === true 366: Ramaze::Log::warn("Failed to serialize #{value.inspect}") 367: end 368: 369: return nil 370: end 371: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.