kiss 0.9
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.
- 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
|