ramaze 2011.01.30 → 2011.07.25

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.
Files changed (229) hide show
  1. data/.gitignore +2 -1
  2. data/.mailmap +2 -0
  3. data/.rvmrc +1 -0
  4. data/README.md +119 -197
  5. data/Rakefile +14 -97
  6. data/bin/ramaze +6 -14
  7. data/doc/AUTHORS +8 -4
  8. data/doc/CHANGELOG +3784 -3339
  9. data/examples/app/chat/start.rb +2 -2
  10. data/lib/proto/app.rb +2 -3
  11. data/lib/proto/config.ru +4 -5
  12. data/lib/proto/controller/init.rb +11 -4
  13. data/lib/proto/controller/main.rb +12 -7
  14. data/lib/proto/layout/default.xhtml +56 -23
  15. data/lib/proto/model/init.rb +3 -1
  16. data/lib/proto/public/css/grid.css +107 -0
  17. data/lib/proto/public/css/layout.css +81 -0
  18. data/lib/proto/public/css/reset.css +123 -0
  19. data/lib/proto/public/css/text.css +109 -0
  20. data/lib/proto/public/images/bg.png +0 -0
  21. data/lib/proto/spec/main.rb +2 -2
  22. data/lib/proto/start.rb +11 -1
  23. data/lib/proto/view/index.xhtml +27 -23
  24. data/lib/ramaze.rb +0 -1
  25. data/lib/ramaze/app.rb +85 -12
  26. data/lib/ramaze/app_graph.rb +107 -0
  27. data/lib/ramaze/bin/console.rb +87 -0
  28. data/lib/ramaze/bin/create.rb +94 -0
  29. data/lib/ramaze/bin/helper.rb +107 -0
  30. data/lib/ramaze/bin/restart.rb +95 -0
  31. data/lib/ramaze/bin/runner.rb +141 -0
  32. data/lib/ramaze/bin/start.rb +206 -0
  33. data/lib/ramaze/bin/status.rb +152 -0
  34. data/lib/ramaze/bin/stop.rb +112 -0
  35. data/lib/ramaze/cache.rb +9 -4
  36. data/lib/ramaze/cache/localmemcache.rb +10 -13
  37. data/lib/ramaze/cache/lru.rb +49 -7
  38. data/lib/ramaze/cache/memcache.rb +170 -92
  39. data/lib/ramaze/cache/sequel.rb +301 -118
  40. data/lib/ramaze/controller.rb +108 -9
  41. data/lib/ramaze/controller/default.rb +15 -2
  42. data/lib/ramaze/current.rb +14 -2
  43. data/lib/ramaze/dependencies.rb +46 -0
  44. data/lib/ramaze/files.rb +38 -3
  45. data/lib/ramaze/gestalt.rb +12 -12
  46. data/lib/ramaze/helper.rb +0 -2
  47. data/lib/ramaze/helper/auth.rb +30 -23
  48. data/lib/ramaze/helper/blue_form.rb +175 -126
  49. data/lib/ramaze/helper/csrf.rb +76 -91
  50. data/lib/ramaze/helper/email.rb +105 -0
  51. data/lib/ramaze/helper/erector.rb +16 -15
  52. data/lib/ramaze/helper/gestalt.rb +2 -2
  53. data/lib/ramaze/helper/layout.rb +89 -73
  54. data/lib/ramaze/helper/link.rb +7 -6
  55. data/lib/ramaze/helper/localize.rb +6 -5
  56. data/lib/ramaze/helper/markaby.rb +25 -23
  57. data/lib/ramaze/helper/maruku.rb +3 -3
  58. data/lib/ramaze/helper/paginate.rb +19 -27
  59. data/lib/ramaze/helper/remarkably.rb +3 -3
  60. data/lib/ramaze/helper/request_accessor.rb +3 -3
  61. data/lib/ramaze/helper/send_file.rb +12 -8
  62. data/lib/ramaze/helper/simple_captcha.rb +5 -6
  63. data/lib/ramaze/helper/stack.rb +7 -4
  64. data/lib/ramaze/helper/tagz.rb +10 -11
  65. data/lib/ramaze/helper/thread.rb +19 -16
  66. data/lib/ramaze/helper/ultraviolet.rb +7 -4
  67. data/lib/ramaze/helper/user.rb +40 -21
  68. data/lib/ramaze/helper/xhtml.rb +29 -20
  69. data/lib/ramaze/log.rb +3 -11
  70. data/lib/ramaze/log/analogger.rb +5 -4
  71. data/lib/ramaze/log/growl.rb +9 -7
  72. data/lib/ramaze/log/hub.rb +3 -5
  73. data/lib/ramaze/log/informer.rb +15 -12
  74. data/lib/ramaze/log/knotify.rb +3 -5
  75. data/lib/ramaze/log/logger.rb +3 -5
  76. data/lib/ramaze/log/logging.rb +6 -8
  77. data/lib/ramaze/log/rotatinginformer.rb +27 -17
  78. data/lib/ramaze/log/syslog.rb +7 -7
  79. data/lib/ramaze/log/xosd.rb +3 -5
  80. data/lib/ramaze/middleware_compiler.rb +27 -4
  81. data/lib/ramaze/reloader.rb +50 -12
  82. data/lib/ramaze/reloader/watch_inotify.rb +4 -5
  83. data/lib/ramaze/reloader/watch_stat.rb +3 -3
  84. data/lib/ramaze/request.rb +18 -8
  85. data/lib/ramaze/response.rb +38 -7
  86. data/lib/ramaze/rest.rb +36 -0
  87. data/lib/ramaze/setup.rb +101 -31
  88. data/lib/ramaze/spec.rb +1 -1
  89. data/lib/ramaze/spec/bacon.rb +6 -3
  90. data/lib/ramaze/spec/helper/bacon.rb +0 -1
  91. data/lib/ramaze/version.rb +1 -1
  92. data/lib/ramaze/view.rb +2 -11
  93. data/lib/ramaze/view/erector.rb +46 -31
  94. data/lib/ramaze/view/erubis.rb +7 -3
  95. data/lib/ramaze/view/ezamar.rb +7 -3
  96. data/lib/ramaze/view/gestalt.rb +9 -3
  97. data/lib/ramaze/view/haml.rb +7 -3
  98. data/lib/ramaze/view/liquid.rb +3 -3
  99. data/lib/ramaze/view/lokar.rb +7 -3
  100. data/lib/ramaze/view/mustache.rb +11 -5
  101. data/lib/ramaze/view/nagoro.rb +3 -3
  102. data/lib/ramaze/view/sass.rb +1 -1
  103. data/lib/ramaze/view/slippers.rb +40 -13
  104. data/lib/ramaze/view/tagz.rb +9 -5
  105. data/ramaze.gemspec +23 -128
  106. data/spec/helper.rb +5 -0
  107. data/spec/ramaze/bin/app/config.ru +11 -0
  108. data/spec/ramaze/bin/create.rb +28 -0
  109. data/spec/ramaze/bin/runner.rb +30 -0
  110. data/spec/ramaze/bin/start.rb +38 -0
  111. data/spec/ramaze/cache/memcache.rb +10 -3
  112. data/spec/ramaze/cache/sequel.rb +7 -0
  113. data/spec/ramaze/controller/provide_inheritance.rb +0 -10
  114. data/spec/ramaze/dispatcher/file.rb +19 -15
  115. data/spec/ramaze/helper/auth.rb +10 -9
  116. data/spec/ramaze/helper/blue_form.rb +121 -68
  117. data/spec/ramaze/helper/email.rb +69 -0
  118. data/spec/ramaze/helper/layout.rb +12 -15
  119. data/spec/ramaze/helper/layout/alternative.xhtml +5 -0
  120. data/spec/ramaze/helper/user.rb +2 -0
  121. data/spec/ramaze/log/growl.rb +14 -1
  122. data/spec/{contrib → ramaze}/rest.rb +1 -1
  123. data/spec/ramaze/session/memcache.rb +2 -2
  124. data/spec/ramaze/view/sass.rb +1 -1
  125. data/tasks/bacon.rake +3 -3
  126. data/tasks/gem.rake +17 -18
  127. data/tasks/rcov.rake +2 -3
  128. data/tasks/release.rake +8 -65
  129. data/tasks/setup.rake +10 -8
  130. data/tasks/todo.rake +9 -5
  131. data/tasks/yard.rake +3 -2
  132. metadata +105 -397
  133. data/MANIFEST +0 -532
  134. data/TODO.md +0 -19
  135. data/benchmark/bench_templates/bench.rb +0 -67
  136. data/benchmark/bench_templates/view/large.erb +0 -79
  137. data/benchmark/bench_templates/view/large.haml +0 -41
  138. data/benchmark/bench_templates/view/large.lok +0 -79
  139. data/benchmark/bench_templates/view/large.xhtml +0 -79
  140. data/benchmark/bench_templates/view/small.erb +0 -21
  141. data/benchmark/bench_templates/view/small.haml +0 -12
  142. data/benchmark/bench_templates/view/small.lok +0 -21
  143. data/benchmark/bench_templates/view/small.xhtml +0 -21
  144. data/benchmark/results.txt +0 -131
  145. data/benchmark/run.rb +0 -355
  146. data/benchmark/suite/minimal.rb +0 -11
  147. data/benchmark/suite/no_informer.rb +0 -7
  148. data/benchmark/suite/no_sessions.rb +0 -9
  149. data/benchmark/suite/no_template.rb +0 -7
  150. data/benchmark/suite/simple.rb +0 -5
  151. data/benchmark/suite/template_erubis.rb +0 -8
  152. data/benchmark/suite/template_etanni.rb +0 -8
  153. data/benchmark/suite/template_ezamar.rb +0 -8
  154. data/benchmark/suite/template_haml.rb +0 -13
  155. data/benchmark/suite/template_liquid.rb +0 -11
  156. data/benchmark/suite/template_markaby.rb +0 -9
  157. data/benchmark/suite/template_nagoro.rb +0 -8
  158. data/benchmark/suite/template_redcloth.rb +0 -13
  159. data/benchmark/suite/template_tenjin.rb +0 -8
  160. data/benchmark/test.rb +0 -35
  161. data/doc/FAQ +0 -92
  162. data/doc/INSTALL +0 -92
  163. data/doc/TODO +0 -29
  164. data/doc/meta/announcement.txt +0 -119
  165. data/doc/meta/configuration.txt +0 -163
  166. data/doc/meta/internals.txt +0 -278
  167. data/doc/meta/users.kml +0 -64
  168. data/doc/tutorial/todolist.html +0 -1512
  169. data/doc/tutorial/todolist.txt +0 -920
  170. data/examples/app/sourceview/public/coderay.css +0 -104
  171. data/examples/app/sourceview/public/images/file.gif +0 -0
  172. data/examples/app/sourceview/public/images/folder.gif +0 -0
  173. data/examples/app/sourceview/public/images/tv-collapsable-last.gif +0 -0
  174. data/examples/app/sourceview/public/images/tv-collapsable.gif +0 -0
  175. data/examples/app/sourceview/public/images/tv-expandable-last.gif +0 -0
  176. data/examples/app/sourceview/public/images/tv-expandable.gif +0 -0
  177. data/examples/app/sourceview/public/images/tv-item-last.gif +0 -0
  178. data/examples/app/sourceview/public/images/tv-item.gif +0 -0
  179. data/examples/app/sourceview/public/jquery.js +0 -11
  180. data/examples/app/sourceview/public/jquery.treeview.css +0 -48
  181. data/examples/app/sourceview/public/jquery.treeview.js +0 -223
  182. data/examples/app/sourceview/public/sourceview.js +0 -52
  183. data/examples/app/sourceview/start.rb +0 -79
  184. data/examples/app/sourceview/view/index.haml +0 -59
  185. data/examples/helpers/httpdigest.rb +0 -107
  186. data/lib/proto/public/css/screen.css +0 -30
  187. data/lib/proto/public/js/jquery.js +0 -7179
  188. data/lib/ramaze/contrib/addressable_route.rb +0 -56
  189. data/lib/ramaze/contrib/app_graph.rb +0 -64
  190. data/lib/ramaze/contrib/email.rb +0 -88
  191. data/lib/ramaze/contrib/facebook.rb +0 -23
  192. data/lib/ramaze/contrib/facebook/facebook.rb +0 -171
  193. data/lib/ramaze/contrib/gettext.rb +0 -113
  194. data/lib/ramaze/contrib/gettext/mo.rb +0 -155
  195. data/lib/ramaze/contrib/gettext/parser.rb +0 -46
  196. data/lib/ramaze/contrib/gettext/po.rb +0 -109
  197. data/lib/ramaze/contrib/gzip_filter.rb +0 -1
  198. data/lib/ramaze/contrib/maruku_uv.rb +0 -59
  199. data/lib/ramaze/contrib/profiling.rb +0 -36
  200. data/lib/ramaze/contrib/rest.rb +0 -23
  201. data/lib/ramaze/contrib/sequel/create_join.rb +0 -26
  202. data/lib/ramaze/contrib/sequel/form_field.rb +0 -129
  203. data/lib/ramaze/contrib/sequel/image.rb +0 -196
  204. data/lib/ramaze/contrib/sequel/relation.rb +0 -98
  205. data/lib/ramaze/helper/httpdigest.rb +0 -96
  206. data/lib/ramaze/tool/bin.rb +0 -340
  207. data/lib/ramaze/tool/create.rb +0 -48
  208. data/lib/ramaze/tool/project_creator.rb +0 -120
  209. data/lib/ramaze/view/less.rb +0 -12
  210. data/lib/ramaze/view/maruku.rb +0 -15
  211. data/lib/ramaze/view/redcloth.rb +0 -21
  212. data/spec/contrib/addressable_route.rb +0 -30
  213. data/spec/examples/helpers/httpdigest.rb +0 -64
  214. data/spec/examples/templates/template_redcloth.rb +0 -13
  215. data/spec/ramaze/bin/ramaze.rb +0 -96
  216. data/spec/ramaze/helper/httpdigest.rb +0 -176
  217. data/spec/ramaze/view/less.rb +0 -60
  218. data/spec/ramaze/view/less/file.css.less +0 -8
  219. data/spec/ramaze/view/redcloth.rb +0 -66
  220. data/spec/ramaze/view/redcloth/external.redcloth +0 -8
  221. data/tasks/copyright.rake +0 -21
  222. data/tasks/gem_setup.rake +0 -112
  223. data/tasks/git.rake +0 -46
  224. data/tasks/grancher.rake +0 -12
  225. data/tasks/jquery.rake +0 -15
  226. data/tasks/manifest.rake +0 -4
  227. data/tasks/metric_changes.rake +0 -24
  228. data/tasks/reversion.rake +0 -8
  229. data/tasks/traits.rake +0 -21
@@ -1,176 +1,359 @@
1
- # Copyright (c) 2009 Michael Fellinger m.fellinger@gmail.com
2
- # All files in this distribution are subject to the terms of the Ruby license.
3
1
  require 'sequel'
4
2
 
5
3
  module Ramaze
6
4
  class Cache
7
5
  ##
8
- # Cache system that uses Sequel to store data in a database table named
9
- # "ramaze_cache". Values stored in the database will be automatically serialized/
10
- # unserialized using Marshal. Originally this cache system didn't work with Sequel 3
11
- # but this has been fixed by Yorick Peterse.
6
+ # The Sequel cache is a cache system that uses the Sequel database toolkit
7
+ # to store the data in a DBMS supported by Sequel. Examples of these
8
+ # databases are MySQL, SQLite3 and so on. In order to use this cache you'd
9
+ # have to do the following:
12
10
  #
13
- # @example
14
- # # Define that we want to use the Sequel cache for sessions
15
- # Ramaze.options.cache.session = Ramaze::Cache::Sequel
11
+ # Ramaze::Cache.options.view = Ramaze::Cache::Sequel.using(
12
+ # :connection => Sequel.mysql(
13
+ # :host => 'localhost',
14
+ # :user => 'user',
15
+ # :password => 'password',
16
+ # :database => 'blog'
17
+ # ),
18
+ # :table => :blog_sessions
19
+ # )
16
20
  #
17
- # # Store some data in the session
18
- # session["framework"] = "Ramaze"
21
+ # If you already have an existing connection you can just pass the object to
22
+ # the :connection option instead of creating a new connection manually.
19
23
  #
20
- # # Do something with the data
21
- # session["framework"] += ", simply (r)amazing"
24
+ # Massive thanks to Lars Olsson for patching the original Sequel cache so
25
+ # that it supports multiple connections and other useful features.
22
26
  #
23
- # @author Unknown, Yorick Peterse
27
+ # @author Lars Olsson
28
+ # @since 18-04-2011
24
29
  #
25
30
  class Sequel
26
- # I can haz API?
27
31
  include Cache::API
32
+ include Innate::Traited
33
+
34
+ # Hash containing the default options
35
+ trait :default => {
36
+ # The default Sequel connection to use
37
+ :connection => nil,
38
+
39
+ # Whether or not warnings should be displayed
40
+ :display_warnings => false,
41
+
42
+ # The name of the default database table to use
43
+ :table => 'ramaze_cache',
44
+
45
+ # The default TTL to use
46
+ :ttl => nil
47
+ }
48
+
49
+ # Hash containing all the default options merged with the user specified
50
+ # ones
51
+ attr_accessor :options
52
+
53
+ class << self
54
+ attr_accessor :options
55
+
56
+ ##
57
+ # This method returns a subclass of Ramaze::Cache::Sequel with the
58
+ # provided options set. This is necessary because Ramaze expects a class
59
+ # and not an instance of a class for its cache option.
60
+ #
61
+ # You can provide any parameters you want, but those not used by the
62
+ # cache will not get stored. No parameters are mandatory. Any missing
63
+ # parameters will be replaced by default values.
64
+ #
65
+ # @example
66
+ # ##
67
+ # # This will create a mysql session cache in the blog
68
+ # # database in the table blog_sessions
69
+ # # Please note that the permissions on the database must
70
+ # # be set up correctly before you can just create a new table
71
+ # #
72
+ # Ramaze.options.cache.session = Ramaze::Cache::Sequel.using(
73
+ # :connection => Sequel.mysql(
74
+ # :host =>'localhost',
75
+ # :user =>'user',
76
+ # :password =>'password',
77
+ # :database =>'blog'
78
+ # ),
79
+ # :table => :blog_sessions
80
+ # )
81
+ #
82
+ # @author Lars Olsson
83
+ # @since 18-04-2011
84
+ # @param [Object] options A hash containing the options to use
85
+ # @option options [Object] :connection a Sequel database object
86
+ # (Sequel::Database) You can use any parameters that Sequel supports for
87
+ # this object. If this option is left unset, a Sqlite memory database
88
+ # will be used.
89
+ # @option options [String] :table The table name you want to use for the
90
+ # cache. Can be either a String or a Symbol. If this option is left
91
+ # unset, a table called ramaze_cache will be used.
92
+ # @option options [Fixnum] :ttl Setting this value will override
93
+ # Ramaze's default setting for when a particular cache item will be
94
+ # invalidated. By default this setting is not used and the cache uses
95
+ # the values provided by Ramaze, but if you want to use this setting it
96
+ # should be set to an integer representing the number of seconds before
97
+ # a cache item becomes invalidated.
98
+ # @option options [TrueClass] :display_warnings When this option is set
99
+ # to true, failure to serialiaze or deserialize cache items will produce
100
+ # a warning in the Ramaze log. This option is set to false by default.
101
+ # Please note that certain objects (for instance Procs) cannot be
102
+ # serialized by ruby and therefore cannot be cached by this cache class.
103
+ # Setting this option to true is a good way to find out if the stuff you
104
+ # are trying to cache is affected by this. Failure to
105
+ # serialize/deserialize a cache item will never raise an exception, the
106
+ # item will just remain uncached.
107
+ # @return [Object]
108
+ #
109
+ def using(options = {})
110
+ merged = Ramaze::Cache::Sequel.trait[:default].merge(options)
111
+ Class.new(self) { @options = merged }
112
+ end
113
+ end
28
114
 
29
115
  ##
30
- # Model used for managing the data in the database.
31
- # All data stored in the "value" column will be serialized/unserialized by Sequel itself.
32
- # The structure of the table that belongs to this model looks like the following:
116
+ # Creates a new instance of the cache class.
33
117
  #
34
- # _________________________________________________________________
35
- # | | | | |
36
- # | (integer) ID | (string) key | (string) value | (date) expires |
37
- # |______________|______________|________________|__________________|
118
+ # @author Michael Fellinger
119
+ # @since 04-05-2011
120
+ # @param [Hash] options A hash with custom options, see
121
+ # Ramaze::Cache::Sequel.using for all available options.
38
122
  #
123
+ def initialize(options = {})
124
+ self.class.options ||= Ramaze::Cache::Sequel.trait[:default].merge(
125
+ options
126
+ )
127
+
128
+ @options = options.merge(self.class.options)
129
+ end
130
+
131
+ ##
132
+ # Executed after #initialize and before any other method.
39
133
  #
40
- # Note that "key" is a unique field so double check to see if your application might try
41
- # to insert an already existing key as this will cause Sequel errors.
134
+ # Some parameters identifying the current process will be passed so caches
135
+ # that act in one global name-space can use them as a prefix.
42
136
  #
43
- # @author Unknown, Yorick Peterse
137
+ # @author Lars Olsson
138
+ # @since 18-04-2011
139
+ # @param [String] hostname the hostname of the machine
140
+ # @param [String] username user executing the process
141
+ # @param [String] appname identifier for the application
142
+ # @param [String] cachename namespace, like 'session' or 'action'
44
143
  #
45
- class Table < ::Sequel::Model(:ramaze_cache)
46
- plugin :schema
47
- plugin :serialization, :marshal, :value
144
+ def cache_setup(hostname, username, appname, cachename)
145
+ @namespace = [hostname, username, appname, cachename].compact.join(':')
48
146
 
49
- # Define the schema for this model
50
- set_schema do
51
- primary_key :id
52
-
53
- String :key, :null => false, :unique => true
54
- String :value, :text => true
55
-
56
- Time :expires
147
+ # Create the table if it's not there yet
148
+ if !options[:connection].table_exists?(options[:table])
149
+ options[:connection].create_table(
150
+ options[:table]) do
151
+ primary_key :id
152
+ String :key , :null => false, :unique => true
153
+ String :value, :text => true
154
+ Time :expires
155
+ end
57
156
  end
58
- end
59
157
 
60
- ##
61
- # Create the cache table if it doesn't exist yet.
62
- # This cache does not yet support multiple applications unless you
63
- # give "app" an unique name.
64
- #
65
- # @author Unknown, Yorick Peterse
66
- # @example
67
- # cache = Ramaze::Cache::Sequel.new
68
- # cache.cache_setup 'my_server', 'chuck_norris', 'blog', 'articles'
69
- #
70
- # @param [String] host The hostname of the machine on which the application is running.
71
- # @param [String] user The user under which the application is running.
72
- # @param [String] app The name of the "application". For example, when using this cache
73
- # for session "app" will be set to "session".
74
- # @param [String] name The name for the row. When using sessions this will be set to the
75
- # user's session ID.
76
- #
77
- def cache_setup(host, user, app, name)
78
- @namespace = [host, user, app, name].compact.join(':')
79
- Table.create_table?
80
- @store = Table
158
+ @dataset = options[:connection][options[:table].to_sym]
81
159
  end
82
160
 
83
161
  ##
84
- # Wipe out _all_ data in the table, use with care!
162
+ # Remove all key/value pairs from the cache. Should behave as if #delete
163
+ # had been called with all +keys+ as argument.
85
164
  #
86
- # @author Unknown, Yorick Peterse
87
- # @example
88
- # cache = Ramaze::Cache::Sequel.new
89
- # cache.cache_clear
165
+ # @author Lars Olsson
166
+ # @since 18-04-2011
90
167
  #
91
168
  def cache_clear
92
- @store.delete
169
+ @dataset.delete
93
170
  end
94
171
 
95
172
  ##
96
- # Deletes a specific set of records based on the provided keys.
173
+ # Remove the corresponding key/value pair for each key passed. If removing
174
+ # is not an option it should set the corresponding value to nil.
97
175
  #
98
- # @author Unknown, Yorick Peterse
99
- # @example
100
- # # Delete everything where "key" is set to "chunky_bacon"
101
- # cache = Ramaze::Cache::Sequel.new
102
- # cache.cache_delete 'chunky_bacon'
176
+ # If only one key was deleted, answer with the corresponding value. If
177
+ # multiple keys were deleted, answer with an Array containing the values.
103
178
  #
104
- # @param [String] *keys A set of keys that define which row has to be deleted.
179
+ # @author Lars Olsson
180
+ # @since 18-04-2011
181
+ # @param [Object] key The key for the value to delete
182
+ # @param [Object] keys Any other keys to delete as well
183
+ # @return [Object/Array/nil]
105
184
  #
106
- def cache_delete(*keys)
107
- if keys
108
- keys.each do |key|
109
- record = @store[:key => namespaced(key)]
110
- record.delete if record
185
+ def cache_delete(key, *keys)
186
+ # Remove a single key
187
+ if keys.empty?
188
+ nkey = namespaced(key)
189
+ result = @dataset.select(:value).filter(:key => nkey).limit(1)
190
+
191
+ # Ramaze expects nil values
192
+ if result.empty?
193
+ result = nil
194
+ else
195
+ result = deserialize(result.first[:value])
111
196
  end
197
+
198
+ @dataset.filter(:key => nkey).delete
199
+ # Remove multiple keys
200
+ else
201
+ nkeys = [key, keys].flatten.map! { |nkey| namespaced(nkey) }
202
+ result = dataset.select(:value).filter(:key => nkeys)
203
+
204
+ result.map! do |row|
205
+ deserialize(row[:value])
206
+ end
207
+
208
+ @dataset.filter(:key => nkeys).delete
112
209
  end
210
+
211
+ return result
113
212
  end
114
213
 
115
214
  ##
116
- # Retrieve the cache that belongs to the specified key.
117
- #
118
- # @author Unknown, Yorick Peterse
119
- # @example
120
- # cache = Ramaze::Cache::Sequel.new
121
- # data = cache.cache_fetch 'chunky_bacon'
215
+ # Answer with the value associated with the +key+, +nil+ if not found or
216
+ # expired.
122
217
  #
123
- # @param [String] key The key that defines what record to retrieve.
124
- # @param [String] default The value to return in case no data could be found.
125
- # @return [String] The unserialized data from the "value" column.
126
- # @return [String]
218
+ # @author Lars Olsson
219
+ # @since 18-04-2011
220
+ # @param [Object] key The key for which to fetch the value
221
+ # @param [Object] default Will return this if no value was found
222
+ # @return [Object]
127
223
  #
128
224
  def cache_fetch(key, default = nil)
129
- # Retrieve the data and return it
130
- record = @store[:key => namespaced(key)]
131
- record.value rescue default
225
+ nkey = namespaced(key)
226
+
227
+ # Delete expired rows
228
+ @dataset.select.filter(:key => nkey) do
229
+ expires < Time.now
230
+ end.delete
231
+
232
+ # Get remaining row (if any)
233
+ result = @dataset.select(:value).filter(:key => nkey).limit(1)
234
+
235
+ if result.empty?
236
+ return default
237
+ else
238
+ return deserialize(result.first[:value])
239
+ end
132
240
  end
133
241
 
134
242
  ##
135
- # Store the specified key/value variables in the cache.
243
+ # Sets the given key to the given value.
136
244
  #
137
- # @author Unknown, Yorick Peterse
138
245
  # @example
139
- # cache = Ramaze::Cache::Sequel.new
140
- # cache.cache_store 'name', 'Yorick Peterse', :ttl => 3600
246
+ # Cache.value.store(:num, 3, :ttl => 20)
247
+ # Cache.value.fetch(:num)
141
248
  #
142
- # @param [String] key The name of the cache to store.
143
- # @param [String] value The actual data to cache.
144
- # @param [Hash] options Additional options such as the TTL.
145
- # @return [String]
249
+ # @author Lars Olsson
250
+ # @since 18-04-2011
251
+ # @param [Object] key The value is stored with this key
252
+ # @param [Object] value The key points to this value
253
+ # @param [Hash] options for now, only :ttl => Fixnum is used.
254
+ # @option options [Fixnum] :ttl The time in seconds after which the cache
255
+ # item should be expired.
146
256
  #
147
257
  def cache_store(key, value, options = {})
148
- key = namespaced(key)
149
- ttl = options[:ttl] rescue nil
150
- expires = Time.now + ttl if !ttl.nil?
151
- record = @store[:key => key]
152
-
153
- # Figure out if the record is new or already exists
154
- if !record
155
- record = @store.create(:key => key, :value => value, :expires => expires)
156
- record.value
258
+ nkey = namespaced(key)
259
+
260
+ # Get the time after which the cache should be expired
261
+ if options[:ttl]
262
+ ttl = options[:ttl]
157
263
  else
158
- record = record.update(:value => value, :expires => expires)
159
- record.value
264
+ ttl = Ramaze::Cache::Sequel.options[:ttl]
160
265
  end
161
- end
266
+
267
+ expires = Time.now + ttl if ttl
268
+
269
+ # The row already exists, update it.
270
+ if @dataset.filter(:key => nkey).count == 1
271
+ serialized_value = serialize(value)
162
272
 
273
+ if serialized_value
274
+ @dataset.update(:value => serialize(value), :expires => expires)
275
+ end
276
+ # The row doesn't exist yet.
277
+ else
278
+ serialized_value = serialize(value)
279
+
280
+ if serialized_value
281
+ @dataset.insert(
282
+ :key => nkey, :value => serialize(value), :expires => expires
283
+ )
284
+ end
285
+ end
286
+
287
+ # Try to deserialize the value. If this fails we'll return a different
288
+ # value
289
+ deserialized = deserialize(@dataset.select(:value).filter(:key => nkey)
290
+ .limit(1).first[:value])
291
+
292
+ if deserialized
293
+ return deserialized
294
+ else
295
+ return value
296
+ end
297
+ end
298
+
163
299
  ##
164
- # Generate the namespace for the cache.
165
- # Namespaces have the format of host:user:app:name:key.
300
+ # Prefixes the given key with current namespace.
166
301
  #
167
- # @author Unknown
168
- # @param [String] key The name of the cache key.
169
- # @return [String]
302
+ # @author Lars Olsson
303
+ # @since 18-04-2011
304
+ # @param [Object] key Key without namespace.
305
+ # @return [Object]
170
306
  #
171
307
  def namespaced(key)
172
- [@namespace, key].join(':')
308
+ return [@namespace, key].join(':')
309
+ end
310
+
311
+ ##
312
+ # Deserialize method, adapted from Sequels serialize plugin
313
+ # This method will try to deserialize a value using Marshal.load
314
+ #
315
+ # @author Lars Olsson
316
+ # @since 18-04-2011
317
+ # @param [Object] value Value to be deserialized
318
+ # @return [Object nil]
319
+ #
320
+ def deserialize(value)
321
+ begin
322
+ ::Marshal.load(value.unpack('m')[0])
323
+ rescue
324
+ begin
325
+ ::Marshal.load(value)
326
+ rescue
327
+ # Log the error?
328
+ if options[:display_warnings] === true
329
+ Ramaze::Log::warn("Failed to deserialize #{value.inspect}")
330
+ end
331
+
332
+ return nil
333
+ end
334
+ end
335
+ end
336
+
337
+ ##
338
+ # Serialize method, adapted from Sequels serialize plugin
339
+ # This method will try to serialize a value using Marshal.dump
340
+ #
341
+ # @author Lars Olsson
342
+ # @since 18-04-2011
343
+ # @param [Object] value Value to be serialized.
344
+ # @return [Object nil]
345
+ #
346
+ def serialize(value)
347
+ begin
348
+ [::Marshal.dump(value)].pack('m')
349
+ rescue
350
+ if options[:display_warnings] === true
351
+ Ramaze::Log::warn("Failed to serialize #{value.inspect}")
352
+ end
353
+
354
+ return nil
355
+ end
173
356
  end
174
- end
175
- end
176
- end
357
+ end # Sequel
358
+ end # Cache
359
+ end # Ramaze