actionpack 1.8.1 → 1.9.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (101) hide show
  1. data/CHANGELOG +309 -16
  2. data/README +1 -1
  3. data/lib/action_controller.rb +5 -0
  4. data/lib/action_controller/assertions.rb +57 -12
  5. data/lib/action_controller/auto_complete.rb +47 -0
  6. data/lib/action_controller/base.rb +288 -258
  7. data/lib/action_controller/benchmarking.rb +8 -3
  8. data/lib/action_controller/caching.rb +88 -42
  9. data/lib/action_controller/cgi_ext/cgi_ext.rb +1 -1
  10. data/lib/action_controller/cgi_ext/cgi_methods.rb +41 -11
  11. data/lib/action_controller/cgi_ext/multipart_progress.rb +169 -0
  12. data/lib/action_controller/cgi_ext/raw_post_data_fix.rb +30 -12
  13. data/lib/action_controller/cgi_process.rb +39 -11
  14. data/lib/action_controller/code_generation.rb +235 -0
  15. data/lib/action_controller/cookies.rb +14 -8
  16. data/lib/action_controller/deprecated_renders_and_redirects.rb +76 -0
  17. data/lib/action_controller/filters.rb +8 -7
  18. data/lib/action_controller/helpers.rb +41 -6
  19. data/lib/action_controller/layout.rb +45 -16
  20. data/lib/action_controller/request.rb +86 -23
  21. data/lib/action_controller/rescue.rb +1 -0
  22. data/lib/action_controller/response.rb +1 -1
  23. data/lib/action_controller/routing.rb +536 -272
  24. data/lib/action_controller/scaffolding.rb +30 -25
  25. data/lib/action_controller/session/active_record_store.rb +251 -50
  26. data/lib/action_controller/streaming.rb +133 -0
  27. data/lib/action_controller/templates/rescues/_request_and_response.rhtml +0 -7
  28. data/lib/action_controller/templates/scaffolds/edit.rhtml +2 -2
  29. data/lib/action_controller/templates/scaffolds/layout.rhtml +22 -18
  30. data/lib/action_controller/templates/scaffolds/list.rhtml +3 -3
  31. data/lib/action_controller/templates/scaffolds/new.rhtml +2 -2
  32. data/lib/action_controller/templates/scaffolds/show.rhtml +1 -1
  33. data/lib/action_controller/test_process.rb +68 -47
  34. data/lib/action_controller/upload_progress.rb +421 -0
  35. data/lib/action_controller/url_rewriter.rb +8 -11
  36. data/lib/action_controller/vendor/html-scanner/html/document.rb +6 -5
  37. data/lib/action_controller/vendor/html-scanner/html/node.rb +70 -14
  38. data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +17 -10
  39. data/lib/action_controller/vendor/html-scanner/html/version.rb +3 -3
  40. data/lib/action_controller/vendor/xml_simple.rb +1019 -0
  41. data/lib/action_controller/verification.rb +36 -30
  42. data/lib/action_view/base.rb +21 -14
  43. data/lib/action_view/helpers/active_record_helper.rb +15 -13
  44. data/lib/action_view/helpers/asset_tag_helper.rb +26 -9
  45. data/lib/action_view/helpers/benchmark_helper.rb +24 -0
  46. data/lib/action_view/helpers/capture_helper.rb +7 -5
  47. data/lib/action_view/helpers/date_helper.rb +63 -46
  48. data/lib/action_view/helpers/form_helper.rb +7 -1
  49. data/lib/action_view/helpers/form_options_helper.rb +19 -11
  50. data/lib/action_view/helpers/form_tag_helper.rb +5 -1
  51. data/lib/action_view/helpers/javascript_helper.rb +403 -35
  52. data/lib/action_view/helpers/javascripts/controls.js +261 -0
  53. data/lib/action_view/helpers/javascripts/dragdrop.js +476 -0
  54. data/lib/action_view/helpers/javascripts/effects.js +570 -0
  55. data/lib/action_view/helpers/javascripts/prototype.js +633 -371
  56. data/lib/action_view/helpers/number_helper.rb +11 -13
  57. data/lib/action_view/helpers/tag_helper.rb +1 -2
  58. data/lib/action_view/helpers/text_helper.rb +69 -6
  59. data/lib/action_view/helpers/upload_progress_helper.rb +433 -0
  60. data/lib/action_view/helpers/url_helper.rb +98 -3
  61. data/lib/action_view/partials.rb +14 -8
  62. data/lib/action_view/vendor/builder/xmlmarkup.rb +11 -0
  63. data/rakefile +13 -5
  64. data/test/abstract_unit.rb +1 -1
  65. data/test/controller/action_pack_assertions_test.rb +52 -9
  66. data/test/controller/active_record_assertions_test.rb +119 -120
  67. data/test/controller/active_record_store_test.rb +111 -0
  68. data/test/controller/addresses_render_test.rb +45 -0
  69. data/test/controller/caching_filestore.rb +92 -0
  70. data/test/controller/capture_test.rb +39 -0
  71. data/test/controller/cgi_test.rb +40 -3
  72. data/test/controller/helper_test.rb +65 -13
  73. data/test/controller/multipart_progress_testx.rb +365 -0
  74. data/test/controller/new_render_test.rb +263 -0
  75. data/test/controller/redirect_test.rb +64 -0
  76. data/test/controller/render_test.rb +20 -21
  77. data/test/controller/request_test.rb +83 -3
  78. data/test/controller/routing_test.rb +702 -0
  79. data/test/controller/send_file_test.rb +2 -0
  80. data/test/controller/test_test.rb +44 -8
  81. data/test/controller/upload_progress_testx.rb +89 -0
  82. data/test/controller/verification_test.rb +94 -29
  83. data/test/fixtures/addresses/list.rhtml +1 -0
  84. data/test/fixtures/test/capturing.rhtml +4 -0
  85. data/test/fixtures/test/list.rhtml +1 -1
  86. data/test/fixtures/test/update_element_with_capture.rhtml +9 -0
  87. data/test/template/active_record_helper_test.rb +30 -15
  88. data/test/template/asset_tag_helper_test.rb +12 -5
  89. data/test/template/benchmark_helper_test.rb +72 -0
  90. data/test/template/date_helper_test.rb +69 -0
  91. data/test/template/form_helper_test.rb +18 -10
  92. data/test/template/form_options_helper_test.rb +40 -5
  93. data/test/template/javascript_helper.rb +149 -2
  94. data/test/template/number_helper_test.rb +2 -0
  95. data/test/template/tag_helper_test.rb +4 -0
  96. data/test/template/text_helper_test.rb +36 -0
  97. data/test/template/upload_progress_helper_testx.rb +272 -0
  98. data/test/template/url_helper_test.rb +30 -0
  99. metadata +30 -6
  100. data/test/controller/layout_test.rb +0 -49
  101. data/test/controller/routing_tests.rb +0 -543
@@ -27,12 +27,12 @@ module ActionController
27
27
  # end
28
28
  #
29
29
  # def show
30
- # @entry = Entry.find(@params["id"])
30
+ # @entry = Entry.find(params[:id])
31
31
  # render_scaffold
32
32
  # end
33
33
  #
34
34
  # def destroy
35
- # Entry.find(@params["id"]).destroy
35
+ # Entry.find(params[:id]).destroy
36
36
  # redirect_to :action => "list"
37
37
  # end
38
38
  #
@@ -42,9 +42,9 @@ module ActionController
42
42
  # end
43
43
  #
44
44
  # def create
45
- # @entry = Entry.new(@params["entry"])
45
+ # @entry = Entry.new(params[:entry])
46
46
  # if @entry.save
47
- # flash["notice"] = "Entry was successfully created"
47
+ # flash[:notice] = "Entry was successfully created"
48
48
  # redirect_to :action => "list"
49
49
  # else
50
50
  # render_scaffold('new')
@@ -52,17 +52,17 @@ module ActionController
52
52
  # end
53
53
  #
54
54
  # def edit
55
- # @entry = Entry.find(@params["id"])
55
+ # @entry = Entry.find(params[:id])
56
56
  # render_scaffold
57
57
  # end
58
58
  #
59
59
  # def update
60
- # @entry = Entry.find(@params["entry"]["id"])
61
- # @entry.attributes = @params["entry"]
60
+ # @entry = Entry.find(params[:id])
61
+ # @entry.attributes = params[:entry]
62
62
  #
63
63
  # if @entry.save
64
- # flash["notice"] = "Entry was successfully updated"
65
- # redirect_to :action => "show/" + @entry.id.to_s
64
+ # flash[:notice] = "Entry was successfully updated"
65
+ # redirect_to :action => "show", :id => @entry
66
66
  # else
67
67
  # render_scaffold('edit')
68
68
  # end
@@ -84,9 +84,9 @@ module ActionController
84
84
  def scaffold(model_id, options = {})
85
85
  validate_options([ :class_name, :suffix ], options.keys)
86
86
 
87
- singular_name = model_id.id2name
88
- class_name = options[:class_name] || Inflector.camelize(singular_name)
89
- plural_name = Inflector.pluralize(singular_name)
87
+ singular_name = model_id.to_s
88
+ class_name = options[:class_name] || singular_name.camelize
89
+ plural_name = singular_name.pluralize
90
90
  suffix = options[:suffix] ? "_#{singular_name}" : ""
91
91
 
92
92
  unless options[:suffix]
@@ -99,17 +99,17 @@ module ActionController
99
99
 
100
100
  module_eval <<-"end_eval", __FILE__, __LINE__
101
101
  def list#{suffix}
102
- @#{singular_name}_pages, @#{plural_name} = paginate :#{singular_name}, :per_page => 10
102
+ @#{singular_name}_pages, @#{plural_name} = paginate :#{plural_name}, :per_page => 10
103
103
  render#{suffix}_scaffold "list#{suffix}"
104
104
  end
105
105
 
106
106
  def show#{suffix}
107
- @#{singular_name} = #{class_name}.find(@params["id"])
107
+ @#{singular_name} = #{class_name}.find(params[:id])
108
108
  render#{suffix}_scaffold
109
109
  end
110
110
 
111
111
  def destroy#{suffix}
112
- #{class_name}.find(@params["id"]).destroy
112
+ #{class_name}.find(params[:id]).destroy
113
113
  redirect_to :action => "list#{suffix}"
114
114
  end
115
115
 
@@ -119,9 +119,9 @@ module ActionController
119
119
  end
120
120
 
121
121
  def create#{suffix}
122
- @#{singular_name} = #{class_name}.new(@params["#{singular_name}"])
122
+ @#{singular_name} = #{class_name}.new(params[:#{singular_name}])
123
123
  if @#{singular_name}.save
124
- flash["notice"] = "#{class_name} was successfully created"
124
+ flash[:notice] = "#{class_name} was successfully created"
125
125
  redirect_to :action => "list#{suffix}"
126
126
  else
127
127
  render#{suffix}_scaffold('new')
@@ -129,17 +129,17 @@ module ActionController
129
129
  end
130
130
 
131
131
  def edit#{suffix}
132
- @#{singular_name} = #{class_name}.find(@params["id"])
132
+ @#{singular_name} = #{class_name}.find(params[:id])
133
133
  render#{suffix}_scaffold
134
134
  end
135
135
 
136
136
  def update#{suffix}
137
- @#{singular_name} = #{class_name}.find(@params["#{singular_name}"]["id"])
138
- @#{singular_name}.attributes = @params["#{singular_name}"]
137
+ @#{singular_name} = #{class_name}.find(params[:id])
138
+ @#{singular_name}.attributes = params[:#{singular_name}]
139
139
 
140
140
  if @#{singular_name}.save
141
- flash["notice"] = "#{class_name} was successfully updated"
142
- redirect_to :action => "show#{suffix}", :id => @#{singular_name}.id.to_s
141
+ flash[:notice] = "#{class_name} was successfully updated"
142
+ redirect_to :action => "show#{suffix}", :id => @#{singular_name}
143
143
  else
144
144
  render#{suffix}_scaffold('edit')
145
145
  end
@@ -148,7 +148,7 @@ module ActionController
148
148
  private
149
149
  def render#{suffix}_scaffold(action = caller_method_name(caller))
150
150
  if template_exists?("\#{self.class.controller_path}/\#{action}")
151
- render_action(action)
151
+ render(:action => action)
152
152
  else
153
153
  @scaffold_class = #{class_name}
154
154
  @scaffold_singular_name, @scaffold_plural_name = "#{singular_name}", "#{plural_name}"
@@ -156,10 +156,15 @@ module ActionController
156
156
  add_instance_variables_to_assigns
157
157
 
158
158
  @content_for_layout = @template.render_file(scaffold_path(action.sub(/#{suffix}$/, "")), false)
159
- self.active_layout ? render_file(self.active_layout, "200 OK", true) : render_file(scaffold_path("layout"))
159
+
160
+ if !active_layout.nil?
161
+ render :file => active_layout, :use_full_path => true
162
+ else
163
+ render :file => scaffold_path("layout")
164
+ end
160
165
  end
161
166
  end
162
-
167
+
163
168
  def scaffold_path(template_name)
164
169
  File.dirname(__FILE__) + "/templates/scaffolds/" + template_name + ".rhtml"
165
170
  end
@@ -1,82 +1,283 @@
1
- begin
2
-
3
- require 'active_record'
4
1
  require 'cgi'
5
2
  require 'cgi/session'
3
+ require 'digest/md5'
6
4
  require 'base64'
7
5
 
8
- # Contributed by Tim Bates
9
6
  class CGI
10
7
  class Session
11
- # Active Record database-based session storage class.
8
+ # A session store backed by an Active Record class.
9
+ #
10
+ # A default class is provided, but any object duck-typing to an Active
11
+ # Record +Session+ class with text +session_id+ and +data+ attributes
12
+ # may be used as the backing store.
13
+ #
14
+ # The default assumes a +sessions+ tables with columns +id+ (numeric
15
+ # primary key), +session_id+ (text), and +data+ (text). Session data is
16
+ # marshaled to +data+. +session_id+ should be indexed for speedy lookups.
12
17
  #
13
- # Implements session storage in a database using the ActiveRecord ORM library. Assumes that the database
14
- # has a table called +sessions+ with columns +id+ (numeric, primary key), +sessid+ and +data+ (text).
15
- # The session data is stored in the +data+ column in the binary Marshal format; the user is responsible for ensuring that
16
- # only data that can be Marshaled is stored in the session.
18
+ # Since the default class is a simple Active Record, you get timestamps
19
+ # for free if you add +created_at+ and +updated_at+ datetime columns to
20
+ # the +sessions+ table, making periodic session expiration a snap.
17
21
  #
18
- # Adding +created_at+ or +updated_at+ datetime columns to the sessions table will enable stamping of the data, which can
19
- # be used to clear out old sessions.
22
+ # You may provide your own session class, whether a feature-packed
23
+ # Active Record or a bare-metal high-performance SQL store, by setting
24
+ # +CGI::Session::ActiveRecordStore.session_class = MySessionClass+
25
+ # You must implement these methods:
26
+ # self.find_by_session_id(session_id)
27
+ # initialize(hash_of_session_id_and_data)
28
+ # attr_reader :session_id
29
+ # attr_accessor :data
30
+ # save!
31
+ # destroy
20
32
  #
21
- # It's highly recommended to have an index on the sessid column to improve performance.
33
+ # The fast SqlBypass class is a generic SQL session store. You may
34
+ # use it as a basis for high-performance database-specific stores.
22
35
  class ActiveRecordStore
23
- # The ActiveRecord class which corresponds to the database table.
36
+ # The default Active Record class.
24
37
  class Session < ActiveRecord::Base
38
+ before_save :marshal_data!
39
+ before_update :data_changed?
40
+
41
+ class << self
42
+ # Hook to set up sessid compatibility.
43
+ def find_by_session_id(session_id)
44
+ setup_sessid_compatibility!
45
+ find_by_session_id(session_id)
46
+ end
47
+
48
+ def marshal(data) Base64.encode64(Marshal.dump(data)) end
49
+ def unmarshal(data) Marshal.load(Base64.decode64(data)) end
50
+ def fingerprint(data) Digest::MD5.hexdigest(data) end
51
+
52
+ def create_table!
53
+ connection.execute <<-end_sql
54
+ CREATE TABLE #{table_name} (
55
+ id INTEGER PRIMARY KEY,
56
+ #{connection.quote_column_name('session_id')} TEXT UNIQUE,
57
+ #{connection.quote_column_name('data')} TEXT
58
+ )
59
+ end_sql
60
+ end
61
+
62
+ def drop_table!
63
+ connection.execute "DROP TABLE #{table_name}"
64
+ end
65
+
66
+ private
67
+ # Compatibility with tables using sessid instead of session_id.
68
+ def setup_sessid_compatibility!
69
+ # Reset column info since it may be stale.
70
+ reset_column_information
71
+ if columns_hash['sessid']
72
+ def self.find_by_session_id(*args)
73
+ find_by_sessid(*args)
74
+ end
75
+
76
+ define_method(:session_id) { sessid }
77
+ define_method(:session_id=) { |session_id| self.sessid = session_id }
78
+ else
79
+ def self.find_by_session_id(session_id)
80
+ find :first, :conditions => ["session_id #{attribute_condition(session_id)}", session_id]
81
+ end
82
+ end
83
+ end
84
+ end
85
+
86
+ # Lazy-unmarshal session state. Take a fingerprint so we can detect
87
+ # whether to save changes later.
88
+ def data
89
+ unless @data
90
+ case @data = read_attribute('data')
91
+ when String
92
+ @fingerprint = self.class.fingerprint(@data)
93
+ @data = self.class.unmarshal(@data)
94
+ when nil
95
+ @data = {}
96
+ @fingerprint = nil
97
+ end
98
+ end
99
+ @data
100
+ end
101
+
102
+ private
103
+ def marshal_data!
104
+ write_attribute('data', self.class.marshal(@data || {}))
105
+ end
106
+
107
+ def data_changed?
108
+ old_fingerprint, @fingerprint = @fingerprint, self.class.fingerprint(read_attribute('data'))
109
+ old_fingerprint != @fingerprint
110
+ end
25
111
  end
26
112
 
27
- # Create a new ActiveRecordStore instance. This constructor is used internally by CGI::Session.
28
- # The user does not generally need to call it directly.
113
+ # A barebones session store which duck-types with the default session
114
+ # store but bypasses Active Record and issues SQL directly.
29
115
  #
30
- # +session+ is the session for which this instance is being created.
116
+ # The database connection, table name, and session id and data columns
117
+ # are configurable class attributes. Marshaling and unmarshaling
118
+ # are implemented as class methods that you may override. By default,
119
+ # marshaling data is +Base64.encode64(Marshal.dump(data))+ and
120
+ # unmarshaling data is +Marshal.load(Base64.decode64(data))+.
31
121
  #
32
- # +option+ is currently ignored as no options are recognized.
33
- #
34
- # This session's ActiveRecord database row will be created if it does not exist, or opened if it does.
35
- def initialize(session, option=nil)
36
- ActiveRecord::Base.silence do
37
- @session = Session.find_by_sessid(session.session_id) || Session.new("sessid" => session.session_id, "data" => marshalize({}))
38
- @data = unmarshalize(@session.data)
122
+ # This marshaling behavior is intended to store the widest range of
123
+ # binary session data in a +text+ column. For higher performance,
124
+ # store in a +blob+ column instead and forgo the Base64 encoding.
125
+ class SqlBypass
126
+ # Use the ActiveRecord::Base.connection by default.
127
+ cattr_accessor :connection
128
+ def self.connection
129
+ @@connection ||= ActiveRecord::Base.connection
39
130
  end
40
- end
41
131
 
42
- # Update and close the session's ActiveRecord object.
43
- def close
44
- return unless @session
45
- update
46
- @session = nil
132
+ # The table name defaults to 'sessions'.
133
+ cattr_accessor :table_name
134
+ @@table_name = 'sessions'
135
+
136
+ # The session id field defaults to 'session_id'.
137
+ cattr_accessor :session_id_column
138
+ @@session_id_column = 'session_id'
139
+
140
+ # The data field defaults to 'data'.
141
+ cattr_accessor :data_column
142
+ @@data_column = 'data'
143
+
144
+ class << self
145
+ # Look up a session by id and unmarshal its data if found.
146
+ def find_by_session_id(session_id)
147
+ if record = @@connection.select_one("SELECT * FROM #{@@table_name} WHERE #{@@session_id_column}=#{@@connection.quote(session_id)}")
148
+ new(:session_id => session_id, :marshaled_data => record['data'])
149
+ end
150
+ end
151
+
152
+ def marshal(data) Base64.encode64(Marshal.dump(data)) end
153
+ def unmarshal(data) Marshal.load(Base64.decode64(data)) end
154
+ def fingerprint(data) Digest::MD5.hexdigest(data) end
155
+
156
+ def create_table!
157
+ @@connection.execute <<-end_sql
158
+ CREATE TABLE #{table_name} (
159
+ id INTEGER PRIMARY KEY,
160
+ #{@@connection.quote_column_name(session_id_column)} TEXT UNIQUE,
161
+ #{@@connection.quote_column_name(data_column)} TEXT
162
+ )
163
+ end_sql
164
+ end
165
+
166
+ def drop_table!
167
+ @@connection.execute "DROP TABLE #{table_name}"
168
+ end
169
+ end
170
+
171
+ attr_reader :session_id
172
+ attr_writer :data
173
+
174
+ # Look for normal and marshaled data, self.find_by_session_id's way of
175
+ # telling us to postpone unmarshaling until the data is requested.
176
+ # We need to handle a normal data attribute in case of a new record.
177
+ def initialize(attributes)
178
+ @session_id, @data, @marshaled_data = attributes[:session_id], attributes[:data], attributes[:marshaled_data]
179
+ @new_record = @marshaled_data.nil?
180
+ end
181
+
182
+ def new_record?
183
+ @new_record
184
+ end
185
+
186
+ # Lazy-unmarshal session state. Take a fingerprint so we can detect
187
+ # whether to save changes later.
188
+ def data
189
+ unless @data
190
+ if @marshaled_data
191
+ @fingerprint = self.class.fingerprint(@marshaled_data)
192
+ @data, @marshaled_data = self.class.unmarshal(@marshaled_data), nil
193
+ else
194
+ @data = {}
195
+ @fingerprint = nil
196
+ end
197
+ end
198
+ @data
199
+ end
200
+
201
+ def save!
202
+ marshaled_data = self.class.marshal(data)
203
+ if @new_record
204
+ @new_record = false
205
+ @@connection.update <<-end_sql, 'Create session'
206
+ INSERT INTO #{@@table_name} (
207
+ #{@@connection.quote_column_name(@@session_id_column)},
208
+ #{@@connection.quote_column_name(@@data_column)} )
209
+ VALUES (
210
+ #{@@connection.quote(session_id)},
211
+ #{@@connection.quote(marshaled_data)} )
212
+ end_sql
213
+ else
214
+ old_fingerprint, @fingerprint = @fingerprint, self.class.fingerprint(marshaled_data)
215
+ if old_fingerprint != @fingerprint
216
+ @@connection.update <<-end_sql, 'Update session'
217
+ UPDATE #{@@table_name}
218
+ SET #{@@connection.quote_column_name(@@data_column)}=#{@@connection.quote(marshaled_data)}
219
+ WHERE #{@@connection.quote_column_name(@@session_id_column)}=#{@@connection.quote(session_id)}
220
+ end_sql
221
+ end
222
+ end
223
+ end
224
+
225
+ def destroy
226
+ unless @new_record
227
+ @@connection.delete <<-end_sql, 'Destroy session'
228
+ DELETE FROM #{@@table_name}
229
+ WHERE #{@@connection.quote_column_name(@@session_id_column)}=#{@@connection.quote(session_id)}
230
+ end_sql
231
+ end
232
+ end
47
233
  end
48
234
 
49
- # Close and destroy the session's ActiveRecord object.
50
- def delete
51
- return unless @session
52
- @session.destroy
53
- @session = nil
235
+ # The class used for session storage. Defaults to
236
+ # CGI::Session::ActiveRecordStore::Session.
237
+ cattr_accessor :session_class
238
+ @@session_class = Session
239
+
240
+ # Find or instantiate a session given a CGI::Session.
241
+ def initialize(session, option = nil)
242
+ session_id = session.session_id
243
+ unless @session = @@session_class.find_by_session_id(session_id)
244
+ unless session.new_session
245
+ raise CGI::Session::NoSession, 'uninitialized session'
246
+ end
247
+ @session = @@session_class.new(:session_id => session_id, :data => {})
248
+ end
54
249
  end
55
250
 
56
- # Restore session state from the session's ActiveRecord object.
251
+ # Restore session state. The session model handles unmarshaling.
57
252
  def restore
58
- return unless @session
59
- @data = unmarshalize(@session.data)
253
+ if @session
254
+ @session.data
255
+ end
60
256
  end
61
257
 
62
- # Save session state in the session's ActiveRecord object.
258
+ # Save session store.
63
259
  def update
64
- return unless @session
65
- ActiveRecord::Base.silence { @session.update_attribute "data", marshalize(@data) }
260
+ if @session
261
+ ActiveRecord::Base.silence { @session.save! }
262
+ end
66
263
  end
67
264
 
68
- private
69
- def unmarshalize(data)
70
- Marshal.load(Base64.decode64(data))
265
+ # Save and close the session store.
266
+ def close
267
+ if @session
268
+ update
269
+ @session = nil
71
270
  end
271
+ end
72
272
 
73
- def marshalize(data)
74
- Base64.encode64(Marshal.dump(data))
273
+ # Delete and close the session store.
274
+ def delete
275
+ if @session
276
+ ActiveRecord::Base.silence { @session.destroy }
277
+ @session = nil
75
278
  end
76
- end #ActiveRecordStore
77
- end #Session
78
- end #CGI
279
+ end
280
+ end
79
281
 
80
- rescue LoadError
81
- # Couldn't load Active Record, so don't make this store available
282
+ end
82
283
  end