kiss 0.9
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +19 -0
- data/Rakefile +33 -0
- data/VERSION +1 -0
- data/lib/kiss/action.rb +204 -0
- data/lib/kiss/controller_accessors.rb +101 -0
- data/lib/kiss/exception_report.rb +359 -0
- data/lib/kiss/form/field.rb +296 -0
- data/lib/kiss/form.rb +414 -0
- data/lib/kiss/format.rb +80 -0
- data/lib/kiss/hacks.rb +140 -0
- data/lib/kiss/iterator.rb +56 -0
- data/lib/kiss/mailer.rb +92 -0
- data/lib/kiss/model.rb +114 -0
- data/lib/kiss/rack/bench.rb +131 -0
- data/lib/kiss/rack/email_errors.rb +64 -0
- data/lib/kiss/rack/facebook.rb +28 -0
- data/lib/kiss/rack/file_not_found.rb +42 -0
- data/lib/kiss/rack/log_exceptions.rb +23 -0
- data/lib/kiss/rack/show_debug.rb +82 -0
- data/lib/kiss/rack/show_exceptions.rb +27 -0
- data/lib/kiss/sequel_mysql.rb +23 -0
- data/lib/kiss/sequel_session.rb +166 -0
- data/lib/kiss/template_methods.rb +125 -0
- data/lib/kiss.rb +725 -0
- metadata +108 -0
@@ -0,0 +1,166 @@
|
|
1
|
+
require 'base64'
|
2
|
+
|
3
|
+
class Kiss
|
4
|
+
# Session store using Sequel.
|
5
|
+
class SequelSession
|
6
|
+
|
7
|
+
# set_schema do
|
8
|
+
# primary_key :id
|
9
|
+
# varchar :session_id
|
10
|
+
# text :data
|
11
|
+
# timestamp :created_at
|
12
|
+
# timestamp :updated_at
|
13
|
+
# end
|
14
|
+
|
15
|
+
attr_accessor :needs_new_cookie
|
16
|
+
|
17
|
+
class << self
|
18
|
+
def setup_storage(controller)
|
19
|
+
unless controller.db.table_exists?(:sessions)
|
20
|
+
controller.db.create_table :sessions do
|
21
|
+
primary_key :id, :null => false
|
22
|
+
column :session_id, :varchar, :null => false
|
23
|
+
column :data, :text
|
24
|
+
column :created_at, :timestamp, :null => false
|
25
|
+
column :updated_at, :timestamp, :null => false
|
26
|
+
index :session_id
|
27
|
+
end
|
28
|
+
|
29
|
+
# db << <<-EOT
|
30
|
+
# CREATE TABLE `sessions` (
|
31
|
+
# `id` int(11) NOT NULL auto_increment,
|
32
|
+
# `session_id` varchar(255) default NULL,
|
33
|
+
# `data` text,
|
34
|
+
# `created_at` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
|
35
|
+
# `updated_at` timestamp NOT NULL default '0000-00-00 00:00:00',
|
36
|
+
# PRIMARY KEY (`id`)
|
37
|
+
# );
|
38
|
+
# EOT
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def rand_uuid
|
43
|
+
values = [
|
44
|
+
rand(0x0010000),
|
45
|
+
rand(0x0010000),
|
46
|
+
rand(0x0010000),
|
47
|
+
rand(0x0010000),
|
48
|
+
rand(0x0010000),
|
49
|
+
rand(0x1000000),
|
50
|
+
rand(0x1000000),
|
51
|
+
]
|
52
|
+
"%04x%04x%04x%04x%04x%06x%06x" % values
|
53
|
+
end
|
54
|
+
|
55
|
+
# Generates a new session ID and creates a row for the new session in the database.
|
56
|
+
def generate
|
57
|
+
new(Sequel::Model(:sessions).create(
|
58
|
+
:session_id => rand_uuid,
|
59
|
+
:data => marshal({}),
|
60
|
+
:created_at => Time.now,
|
61
|
+
:updated_at => Time.now
|
62
|
+
))
|
63
|
+
end
|
64
|
+
|
65
|
+
# Gets the existing session based on the <tt>session_id</tt> available in cookies.
|
66
|
+
# If none is found, generates a new session.
|
67
|
+
def persist(session_id)
|
68
|
+
if session_id
|
69
|
+
if object = Sequel::Model(:sessions).where(:session_id => session_id).first
|
70
|
+
session = new( object )
|
71
|
+
end
|
72
|
+
end
|
73
|
+
unless session
|
74
|
+
session = generate
|
75
|
+
end
|
76
|
+
session
|
77
|
+
end
|
78
|
+
|
79
|
+
# Don't try to reload ARStore::Session in dev mode.
|
80
|
+
def reloadable? #:nodoc:
|
81
|
+
false
|
82
|
+
end
|
83
|
+
|
84
|
+
# good
|
85
|
+
def marshal(data)
|
86
|
+
Base64.encode64(Marshal.dump(data)) if data
|
87
|
+
end
|
88
|
+
|
89
|
+
# good
|
90
|
+
def unmarshal(data)
|
91
|
+
Marshal.load(Base64.decode64(data)) if data
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def initialize(object)
|
96
|
+
@object = object
|
97
|
+
@data = self.class.unmarshal(@object[:data]) || {}
|
98
|
+
end
|
99
|
+
|
100
|
+
def values(*args)
|
101
|
+
@object.values(*args)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Regenerate the Session ID
|
105
|
+
def regenerate
|
106
|
+
@object.update_attributes(:session_id => Kiss::SessionMixin::rand_uuid)
|
107
|
+
@needs_new_cookie = true
|
108
|
+
end
|
109
|
+
|
110
|
+
# Recreates the cookie with the default expiration time
|
111
|
+
# Useful during log in for pushing back the expiration date
|
112
|
+
def refresh_expiration
|
113
|
+
@needs_new_cookie = true
|
114
|
+
end
|
115
|
+
|
116
|
+
# good
|
117
|
+
# Lazy-delete of session data
|
118
|
+
def delete(key = nil)
|
119
|
+
key ? self.data.delete(key) : self.data.clear
|
120
|
+
end
|
121
|
+
|
122
|
+
# good
|
123
|
+
def [](key)
|
124
|
+
data[key]
|
125
|
+
end
|
126
|
+
|
127
|
+
# good
|
128
|
+
def []=(key, val)
|
129
|
+
data[key] = val
|
130
|
+
end
|
131
|
+
|
132
|
+
# good
|
133
|
+
def empty?
|
134
|
+
data.empty?
|
135
|
+
end
|
136
|
+
|
137
|
+
# good
|
138
|
+
def each(&b)
|
139
|
+
data.each(&b)
|
140
|
+
end
|
141
|
+
|
142
|
+
# good
|
143
|
+
# Lazy-unmarshal session state.
|
144
|
+
def data
|
145
|
+
@data
|
146
|
+
end
|
147
|
+
|
148
|
+
# good
|
149
|
+
# Has the session been loaded yet?
|
150
|
+
def loaded?
|
151
|
+
!! @data
|
152
|
+
end
|
153
|
+
|
154
|
+
# good
|
155
|
+
def save
|
156
|
+
@object[:data] = self.class.marshal(self.data)
|
157
|
+
@object[:updated_at] = Time.now
|
158
|
+
@object.save
|
159
|
+
end
|
160
|
+
|
161
|
+
private
|
162
|
+
|
163
|
+
attr_writer :data
|
164
|
+
|
165
|
+
end
|
166
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
class Kiss
|
2
|
+
module TemplateMethods
|
3
|
+
include Kiss::ControllerAccessors
|
4
|
+
|
5
|
+
# Contains data set by action/mailer logic to be displayed in templates.
|
6
|
+
def data
|
7
|
+
@data
|
8
|
+
end
|
9
|
+
alias_method :vars, :data
|
10
|
+
|
11
|
+
# Merges specified data (key-value pairs) into template data hash.
|
12
|
+
def set(vars)
|
13
|
+
vars.each_pair do |key,value|
|
14
|
+
# convert symbols to strings
|
15
|
+
@data[key.to_s] = value
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Shorthand to access vars.title, here for backward compatibility.
|
20
|
+
# Note: @title is deprecated for use in templates and will not be
|
21
|
+
# supported in Kiss 1.0. Use title and title= instead.
|
22
|
+
def title
|
23
|
+
vars.title
|
24
|
+
end
|
25
|
+
|
26
|
+
# Shorthand to set vars.title, here for backward compatibility.
|
27
|
+
# Note: @title is deprecated for use in templates and will not be
|
28
|
+
# supported in Kiss 1.0. Use title and title= instead.
|
29
|
+
def title=(new_title)
|
30
|
+
vars.title = new_title
|
31
|
+
@title = new_title
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns value of next layout file, which will be used to wrap the
|
35
|
+
# results of current rendering template.
|
36
|
+
# Note: @layout is deprecated for use in templates and will not be
|
37
|
+
# supported in Kiss 1.0. Use layout and layout= instead.
|
38
|
+
def layout
|
39
|
+
# @layout deprecated; future will be action.layout
|
40
|
+
@layout
|
41
|
+
end
|
42
|
+
|
43
|
+
# Sets path to next layout file, which will be used to wrap the
|
44
|
+
# results of current rendering template.
|
45
|
+
# Note: @layout is deprecated for use in templates and will not be
|
46
|
+
# supported in Kiss 1.0. Use layout and layout= instead.
|
47
|
+
def layout=(new_layout)
|
48
|
+
# @layout deprecated; future will be action.layout
|
49
|
+
@layout = new_layout
|
50
|
+
end
|
51
|
+
|
52
|
+
# Reads file specified by options and return contents (without template
|
53
|
+
# processing).
|
54
|
+
def insert(options = {})
|
55
|
+
path = get_template_path(options)
|
56
|
+
content = File.read(path)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Processes template specified by options and return results.
|
60
|
+
def process(options = {})
|
61
|
+
path = get_template_path(options)
|
62
|
+
content = erubis(path,binding)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Gets path to insert/template file from specified options.
|
66
|
+
def get_template_path(options)
|
67
|
+
@current_template_dir ||= @template_dir
|
68
|
+
|
69
|
+
path = options.is_a?(String) ? options : "#{options[:template]}.#{options[:extension] || 'rhtml'}"
|
70
|
+
path = path =~ /\A\// ? "#{@template_dir}#{path}" : "#{@current_template_dir}/#{path}"
|
71
|
+
|
72
|
+
path
|
73
|
+
end
|
74
|
+
|
75
|
+
# Processes specified template file using specified binding.
|
76
|
+
# content is used to pass previously rendered results into
|
77
|
+
# wrapper templates such as layouts.
|
78
|
+
def erubis(path,template_binding = binding,content = nil)
|
79
|
+
# params note: content (if provided) is passed to erubis template via binding
|
80
|
+
|
81
|
+
# set template dir to dir that contains this template
|
82
|
+
@current_template_dir ||= @template_dir
|
83
|
+
old_template_dir = @current_template_dir
|
84
|
+
@current_template_dir = path.sub(/\/?[^\/]*\Z/,'')
|
85
|
+
|
86
|
+
eruby_src = file_cache(path,'template') do |template|
|
87
|
+
# macros
|
88
|
+
template.gsub!(/\<\%\s*macro\s+(\w+.*?)\s*\%\>/,'<% def \1; _buf = \'\' %>')
|
89
|
+
template.gsub!(/\<\%\s*end\s+macro\s*\%\>/,'<% _buf; end %>')
|
90
|
+
|
91
|
+
# for loop iterator
|
92
|
+
template.gsub!(/\<\%\s*for\s+(\w+)\s+in\s+(.*?)\s*\%\>/,'<% loop = Kiss::Iterator.new(\2); for \1 in loop.collection; loop.increment %>')
|
93
|
+
# while loop iterator
|
94
|
+
template.gsub!(/\<\%\s*while\s+(.*?)\s*\%\>/,'<% loop = Kiss::Iterator.new; while \1; loop.increment %>')
|
95
|
+
|
96
|
+
Erubis::Eruby.new(template).src
|
97
|
+
end
|
98
|
+
result = eval eruby_src, template_binding, path
|
99
|
+
|
100
|
+
# restore previous template dir
|
101
|
+
@template_dir = old_template_dir
|
102
|
+
|
103
|
+
result
|
104
|
+
end
|
105
|
+
|
106
|
+
# Escapes string for use in URLs.
|
107
|
+
def url_encode(string)
|
108
|
+
# don't encode to hex: letters, numbers, periods, spaces
|
109
|
+
# encode space to +
|
110
|
+
string.gsub(/([^A-Za-z0-9\.])/) { sprintf("%%%02X", $&.unpack("C")[0]) }
|
111
|
+
end
|
112
|
+
alias_method :escape, :url_encode
|
113
|
+
alias_method :h, :url_encode
|
114
|
+
|
115
|
+
# Encodes string for output to HTML.
|
116
|
+
def escape_html(str)
|
117
|
+
Rack::Utils.escape_html(str)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Formats number to two decimal places.
|
121
|
+
def currency(num)
|
122
|
+
sprintf("%0.2f",num.to_f)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|