ramaze 2011.07.25 → 2011.10.23
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/.gitignore +3 -0
- data/.mailmap +3 -2
- data/.travis.yml +17 -0
- data/.yardopts +13 -0
- data/README.md +95 -352
- data/examples/app/blog/app.rb +25 -64
- data/examples/app/blog/config.ru +11 -9
- data/examples/app/blog/controller/init.rb +29 -86
- data/examples/app/blog/controller/posts.rb +232 -0
- data/examples/app/blog/controller/users.rb +160 -0
- data/examples/app/blog/layout/default.xhtml +61 -0
- data/examples/app/blog/migrations/01_create_schema.rb +50 -0
- data/examples/app/blog/model/comment.rb +41 -54
- data/examples/app/blog/model/init.rb +41 -13
- data/examples/app/blog/model/post.rb +35 -0
- data/examples/app/blog/model/user.rb +105 -0
- data/examples/app/blog/public/.htaccess +24 -0
- data/examples/app/blog/public/css/grid.css +107 -0
- data/examples/app/blog/public/css/layout.css +203 -0
- data/examples/app/blog/public/css/reset.css +123 -0
- data/examples/app/blog/public/css/text.css +109 -0
- data/examples/app/blog/public/dispatch.fcgi +11 -0
- data/examples/app/blog/public/favicon.ico +0 -0
- data/examples/app/blog/public/images/bg.png +0 -0
- data/examples/app/blog/start.rb +18 -3
- data/examples/app/blog/view/feed.xhtml +23 -0
- data/examples/app/blog/view/form.xhtml +11 -0
- data/examples/app/blog/view/index.xhtml +44 -0
- data/examples/app/blog/view/users/form.xhtml +12 -0
- data/examples/app/blog/view/users/index.xhtml +30 -0
- data/examples/app/blog/view/users/login.xhtml +8 -0
- data/examples/app/blog/view/view.xhtml +68 -0
- data/{doc → guide}/AUTHORS +5 -3
- data/{doc → guide}/CHANGELOG +428 -0
- data/{doc/GPL → guide/GPL_LICENSE} +0 -0
- data/{doc/COPYING → guide/RUBY_LICENSE} +3 -6
- data/guide/_static/logo.png +0 -0
- data/guide/_static/logo.svg +49 -0
- data/guide/_static/ramaze_console.png +0 -0
- data/guide/css/common.css +20 -0
- data/guide/general/cache.md +167 -0
- data/guide/general/configuration.md +168 -0
- data/guide/general/contributing.md +108 -0
- data/guide/general/controllers.md +115 -0
- data/guide/general/helpers.md +76 -0
- data/guide/general/installation.md +58 -0
- data/guide/general/logging.md +99 -0
- data/guide/general/middlewares.md +100 -0
- data/guide/general/models.md +78 -0
- data/guide/general/principles.md +53 -0
- data/guide/general/ramaze_command.md +155 -0
- data/guide/general/routes.md +81 -0
- data/guide/general/sessions.md +140 -0
- data/guide/general/special_thanks.md +67 -0
- data/guide/general/testing.md +61 -0
- data/guide/general/views.md +322 -0
- data/guide/tutorials/introduction.md +259 -0
- data/lib/proto/config.ru +1 -1
- data/lib/proto/public/favicon.ico +0 -0
- data/lib/proto/view/index.xhtml +7 -7
- data/lib/ramaze.rb +4 -4
- data/lib/ramaze/app.rb +11 -11
- data/lib/ramaze/app_graph.rb +2 -4
- data/lib/ramaze/bin/console.rb +3 -3
- data/lib/ramaze/bin/create.rb +2 -2
- data/lib/ramaze/bin/restart.rb +4 -4
- data/lib/ramaze/bin/runner.rb +5 -5
- data/lib/ramaze/bin/start.rb +19 -4
- data/lib/ramaze/bin/status.rb +3 -3
- data/lib/ramaze/bin/stop.rb +3 -3
- data/lib/ramaze/cache.rb +1 -0
- data/lib/ramaze/cache/lru.rb +8 -4
- data/lib/ramaze/cache/memcache.rb +32 -13
- data/lib/ramaze/cache/redis.rb +164 -0
- data/lib/ramaze/cache/sequel.rb +43 -28
- data/lib/ramaze/controller.rb +1 -2
- data/lib/ramaze/dependencies.rb +40 -3
- data/lib/ramaze/helper/bench.rb +26 -16
- data/lib/ramaze/helper/blue_form.rb +46 -73
- data/lib/ramaze/helper/cache.rb +10 -6
- data/lib/ramaze/helper/csrf.rb +35 -39
- data/lib/ramaze/helper/disqus.rb +5 -4
- data/lib/ramaze/helper/email.rb +35 -24
- data/lib/ramaze/helper/erector.rb +9 -13
- data/lib/ramaze/helper/flash.rb +7 -9
- data/lib/ramaze/helper/formatting.rb +194 -179
- data/lib/ramaze/helper/gravatar.rb +4 -8
- data/lib/ramaze/helper/identity.rb +3 -3
- data/lib/ramaze/helper/layout.rb +23 -8
- data/lib/ramaze/helper/markaby.rb +1 -1
- data/lib/ramaze/helper/paginate.rb +46 -39
- data/lib/ramaze/helper/request_accessor.rb +3 -1
- data/lib/ramaze/helper/simple_captcha.rb +18 -17
- data/lib/ramaze/helper/stack.rb +1 -1
- data/lib/ramaze/helper/tagz.rb +4 -2
- data/lib/ramaze/helper/upload.rb +523 -0
- data/lib/ramaze/helper/user.rb +4 -8
- data/lib/ramaze/helper/xhtml.rb +11 -15
- data/lib/ramaze/log.rb +9 -6
- data/lib/ramaze/log/rotatinginformer.rb +62 -27
- data/lib/ramaze/log/syslog.rb +20 -15
- data/lib/ramaze/log/xosd.rb +2 -1
- data/lib/ramaze/reloader.rb +2 -0
- data/lib/ramaze/request.rb +11 -10
- data/lib/ramaze/setup.rb +23 -6
- data/lib/ramaze/snippets/array/put_within.rb +3 -9
- data/lib/ramaze/snippets/binding/locals.rb +5 -10
- data/lib/ramaze/snippets/fiber.rb +1 -23
- data/lib/ramaze/snippets/kernel/pretty_inspect.rb +3 -6
- data/lib/ramaze/snippets/numeric/filesize_format.rb +3 -5
- data/lib/ramaze/snippets/numeric/time.rb +3 -7
- data/lib/ramaze/snippets/object/__dir__.rb +3 -7
- data/lib/ramaze/snippets/object/instance_variable_defined.rb +3 -6
- data/lib/ramaze/snippets/object/pretty.rb +3 -7
- data/lib/ramaze/snippets/object/scope.rb +7 -9
- data/lib/ramaze/snippets/proc/locals.rb +12 -12
- data/lib/ramaze/snippets/ramaze/acquire.rb +15 -14
- data/lib/ramaze/snippets/ramaze/deprecated.rb +1 -1
- data/lib/ramaze/snippets/ramaze/fiber.rb +1 -1
- data/lib/ramaze/snippets/ramaze/lru_hash.rb +2 -3
- data/lib/ramaze/snippets/ramaze/struct.rb +2 -4
- data/lib/ramaze/snippets/string/camel_case.rb +8 -10
- data/lib/ramaze/snippets/string/color.rb +3 -4
- data/lib/ramaze/snippets/string/end_with.rb +3 -6
- data/lib/ramaze/snippets/string/esc.rb +3 -8
- data/lib/ramaze/snippets/string/ord.rb +3 -8
- data/lib/ramaze/snippets/string/snake_case.rb +6 -9
- data/lib/ramaze/snippets/string/start_with.rb +3 -8
- data/lib/ramaze/snippets/string/unindent.rb +3 -6
- data/lib/ramaze/snippets/thread/into.rb +1 -3
- data/lib/ramaze/spec.rb +2 -31
- data/lib/ramaze/spec/bacon.rb +18 -2
- data/lib/ramaze/version.rb +1 -1
- data/lib/ramaze/view.rb +1 -1
- data/ramaze.gemspec +1 -1
- data/spec/helper.rb +2 -1
- data/spec/ramaze/bin/start.rb +16 -20
- data/spec/ramaze/cache/localmemcache.rb +4 -7
- data/spec/ramaze/cache/memcache.rb +3 -1
- data/spec/ramaze/cache/redis.rb +62 -0
- data/spec/ramaze/helper/blue_form.rb +33 -4
- data/spec/ramaze/helper/layout.rb +40 -7
- data/spec/ramaze/helper/upload.rb +149 -0
- data/spec/ramaze/helper/uploads/text_1.txt +1 -0
- data/spec/ramaze/helper/uploads/text_2.txt +1 -0
- data/spec/ramaze/log/growl.rb +4 -6
- data/spec/ramaze/log/syslog.rb +6 -0
- data/spec/ramaze/view/lokar.rb +5 -0
- data/spec/ramaze/view/nagoro.rb +5 -0
- data/tasks/authors.rake +1 -1
- data/tasks/bacon.rake +14 -5
- data/tasks/changelog.rake +1 -1
- data/tasks/yard.rake +12 -4
- metadata +277 -239
- data/doc/LEGAL +0 -26
- data/examples/app/blog/README +0 -3
- data/examples/app/blog/controller/comment.rb +0 -45
- data/examples/app/blog/controller/entry.rb +0 -85
- data/examples/app/blog/controller/main.rb +0 -20
- data/examples/app/blog/controller/tag.rb +0 -9
- data/examples/app/blog/layout/default.nag +0 -31
- data/examples/app/blog/model/entry.rb +0 -89
- data/examples/app/blog/model/tag.rb +0 -36
- data/examples/app/blog/public/css/screen.css +0 -273
- data/examples/app/blog/spec/blog.rb +0 -87
- data/examples/app/blog/view/comment/form.nag +0 -10
- data/examples/app/blog/view/comment/show.nag +0 -16
- data/examples/app/blog/view/entry/edit.nag +0 -14
- data/examples/app/blog/view/entry/feed.atom.nag +0 -8
- data/examples/app/blog/view/entry/feed.rss.nag +0 -7
- data/examples/app/blog/view/entry/index.nag +0 -7
- data/examples/app/blog/view/entry/new.nag +0 -13
- data/examples/app/blog/view/entry/show.nag +0 -36
- data/examples/app/blog/view/feed.atom.nag +0 -18
- data/examples/app/blog/view/feed.rss.nag +0 -25
- data/examples/app/blog/view/index.nag +0 -6
- data/examples/app/blog/view/tag/index.nag +0 -5
- data/lib/proto/public/ramaze.png +0 -0
- data/lib/ramaze/rest.rb +0 -36
- data/spec/ramaze/rest.rb +0 -28
- data/tasks/rcov.rake +0 -22
data/lib/ramaze/helper/csrf.rb
CHANGED
|
@@ -17,29 +17,29 @@ module Ramaze
|
|
|
17
17
|
# However, there's no need to panic as it's very easy to setup a basic anti
|
|
18
18
|
# CSRF system.
|
|
19
19
|
#
|
|
20
|
-
#
|
|
20
|
+
# ## Usage
|
|
21
21
|
#
|
|
22
22
|
# In order to enable CSRF protection we need to do two things. Load the
|
|
23
23
|
# helper and create a before_all block in a controller. Take a look at the
|
|
24
24
|
# following code:
|
|
25
25
|
#
|
|
26
|
-
#
|
|
27
|
-
#
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
#
|
|
26
|
+
# class BaseController < Ramaze::Controller
|
|
27
|
+
# before_all do
|
|
28
|
+
# puts "Hello, before_all!"
|
|
29
|
+
# end
|
|
30
|
+
# end
|
|
31
31
|
#
|
|
32
32
|
# This would output "Hello, before_all!" to the console upon each request.
|
|
33
33
|
# Not very useful but it does show what the before_all block can do. On to
|
|
34
34
|
# actual CSRF related code!
|
|
35
35
|
#
|
|
36
|
-
#
|
|
37
|
-
#
|
|
38
|
-
#
|
|
39
|
-
#
|
|
40
|
-
#
|
|
41
|
-
#
|
|
42
|
-
#
|
|
36
|
+
# class BaseController < Ramaze::Controller
|
|
37
|
+
# before_all do
|
|
38
|
+
# csrf_protection :save do
|
|
39
|
+
# # ....
|
|
40
|
+
# end
|
|
41
|
+
# end
|
|
42
|
+
# end
|
|
43
43
|
#
|
|
44
44
|
# This example introduces an extra block that validates the current
|
|
45
45
|
# request. Whenever a user requests a controller that either extends
|
|
@@ -47,13 +47,13 @@ module Ramaze
|
|
|
47
47
|
# current request data contains a CSRF token. Of course an if/end isn't
|
|
48
48
|
# very useful if it doesn't do anything, let's add some code.
|
|
49
49
|
#
|
|
50
|
-
#
|
|
51
|
-
#
|
|
52
|
-
#
|
|
53
|
-
#
|
|
54
|
-
#
|
|
55
|
-
#
|
|
56
|
-
#
|
|
50
|
+
# class BaseController < Ramaze::Controller
|
|
51
|
+
# before_all do
|
|
52
|
+
# csrf_protection :save do
|
|
53
|
+
# puts "Hello, unsafe data!"
|
|
54
|
+
# end
|
|
55
|
+
# end
|
|
56
|
+
# end
|
|
57
57
|
#
|
|
58
58
|
# The code above checks if the current method is "save" (or any other of
|
|
59
59
|
# the provided methods) and checks if an CSRF token is supplied if the
|
|
@@ -67,18 +67,17 @@ module Ramaze
|
|
|
67
67
|
# If you're a lazy person you can copy-paste the example below and adapt it
|
|
68
68
|
# to your needs.
|
|
69
69
|
#
|
|
70
|
-
#
|
|
71
|
-
#
|
|
72
|
-
#
|
|
73
|
-
#
|
|
74
|
-
#
|
|
75
|
-
#
|
|
76
|
-
#
|
|
70
|
+
# class BaseController < Ramaze::Controller
|
|
71
|
+
# before_all do
|
|
72
|
+
# csrf_protection :save do
|
|
73
|
+
# respond("The supplied CSRF token is invalid.", 401)
|
|
74
|
+
# end
|
|
75
|
+
# end
|
|
76
|
+
# end
|
|
77
77
|
#
|
|
78
78
|
# @author Yorick Peterse
|
|
79
79
|
#
|
|
80
80
|
module CSRF
|
|
81
|
-
|
|
82
81
|
##
|
|
83
82
|
# Method that can be used to protect the specified methods against CSRF
|
|
84
83
|
# exploits. Each protected method will require the token to be stored in
|
|
@@ -86,10 +85,10 @@ module Ramaze
|
|
|
86
85
|
# against the current token in the session.
|
|
87
86
|
#
|
|
88
87
|
# @author Yorick Peterse
|
|
89
|
-
# @param [Strings/Symbol] *methods Methods that will be
|
|
88
|
+
# @param [Strings/Symbol] *methods Methods that will be
|
|
89
|
+
# protected/unprotected.
|
|
90
90
|
# @param [Block] Block that will be executed if the token is invalid.
|
|
91
91
|
# @example
|
|
92
|
-
#
|
|
93
92
|
# # Protect "create" and "save" against CSRF exploits
|
|
94
93
|
# before_all do
|
|
95
94
|
# csrf_protection :create, :save do
|
|
@@ -97,7 +96,7 @@ module Ramaze
|
|
|
97
96
|
# end
|
|
98
97
|
# end
|
|
99
98
|
#
|
|
100
|
-
def csrf_protection
|
|
99
|
+
def csrf_protection(*methods, &block)
|
|
101
100
|
# Only protect the specified methods
|
|
102
101
|
if methods.include?(action.name) or methods.include?(action.name.to_sym)
|
|
103
102
|
# THINK: For now the field name is hard-coded to "csrf_token". While
|
|
@@ -120,9 +119,8 @@ module Ramaze
|
|
|
120
119
|
#
|
|
121
120
|
# @author Yorick Peterse
|
|
122
121
|
# @param [Hash] Additional arguments that can be set such as the TTL.
|
|
123
|
-
# @return [Void]
|
|
124
122
|
#
|
|
125
|
-
def generate_csrf_token
|
|
123
|
+
def generate_csrf_token(args = {})
|
|
126
124
|
# Default TTL is 15 minutes
|
|
127
125
|
ttl = args[:ttl] || (15 * 60)
|
|
128
126
|
|
|
@@ -154,7 +152,6 @@ module Ramaze
|
|
|
154
152
|
# @author Yorick Peterse
|
|
155
153
|
# @return [String] The current CSRF token.
|
|
156
154
|
# @example
|
|
157
|
-
#
|
|
158
155
|
# form(@data, :method => :post) do |f|
|
|
159
156
|
# f.input_hidden :csrf_token, get_csrf_token()
|
|
160
157
|
# end
|
|
@@ -180,9 +177,8 @@ module Ramaze
|
|
|
180
177
|
#
|
|
181
178
|
# @author Yorick Peterse
|
|
182
179
|
# @param [String] input_token The CSRF token to validate.
|
|
183
|
-
# @return [
|
|
180
|
+
# @return [TrueClass|FalseClass]
|
|
184
181
|
# @example
|
|
185
|
-
#
|
|
186
182
|
# before_all do
|
|
187
183
|
# if validate_csrf_token(request.params['csrf_token']) != true
|
|
188
184
|
# respond("Invalid CSRF token", 401)
|
|
@@ -205,6 +201,6 @@ module Ramaze
|
|
|
205
201
|
_csrf[:ip] == request.env['REMOTE_ADDR'] &&
|
|
206
202
|
_csrf[:agent] == request.env['HTTP_USER_AGENT']
|
|
207
203
|
end
|
|
208
|
-
end
|
|
209
|
-
end
|
|
210
|
-
end
|
|
204
|
+
end # CSRF
|
|
205
|
+
end # Helper
|
|
206
|
+
end # Ramaze
|
data/lib/ramaze/helper/disqus.rb
CHANGED
|
@@ -3,7 +3,7 @@ require 'disqus/view_helpers'
|
|
|
3
3
|
|
|
4
4
|
module Ramaze
|
|
5
5
|
module Helper
|
|
6
|
-
|
|
6
|
+
##
|
|
7
7
|
# Provides shortcuts via Disqus::ViewHelpers.
|
|
8
8
|
#
|
|
9
9
|
# Make sure that you set your disqus credentials when using this helper:
|
|
@@ -19,8 +19,9 @@ module Ramaze
|
|
|
19
19
|
# disqus_recent_comments
|
|
20
20
|
# disqus_thread
|
|
21
21
|
# disqus_top_commenters
|
|
22
|
+
#
|
|
22
23
|
module Disqus
|
|
23
24
|
include ::Disqus::ViewHelpers
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
|
25
|
+
end # Disqus
|
|
26
|
+
end # Helper
|
|
27
|
+
end # Ramaze
|
data/lib/ramaze/helper/email.rb
CHANGED
|
@@ -6,35 +6,37 @@ module Ramaze
|
|
|
6
6
|
# The Email helper can be used as a simple way of sending Emails from your
|
|
7
7
|
# application. In order to use this helper you first need to load it:
|
|
8
8
|
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
9
|
+
# class Comments < Ramaze::Controller
|
|
10
|
+
# helper :email
|
|
11
|
+
# end
|
|
12
12
|
#
|
|
13
13
|
# Sending an Email can be done by calling the method send_email():
|
|
14
14
|
#
|
|
15
|
-
#
|
|
15
|
+
# send_email(
|
|
16
|
+
# 'user@domain.tld',
|
|
17
|
+
# 'Hello, world!',
|
|
18
|
+
# 'Hello, this is an Email'
|
|
19
|
+
# )
|
|
16
20
|
#
|
|
17
|
-
# Ramaze will log any errors in case the Email could not be sent so you
|
|
18
|
-
# worry about this.
|
|
21
|
+
# Ramaze will log any errors in case the Email could not be sent so you
|
|
22
|
+
# don't have to worry about this.
|
|
19
23
|
#
|
|
20
|
-
#
|
|
24
|
+
# ## Options
|
|
21
25
|
#
|
|
22
|
-
# This module can be configured using Innate::Optioned. Say you want to
|
|
23
|
-
# SMTP host you simply need to do the following:
|
|
26
|
+
# This module can be configured using Innate::Optioned. Say you want to
|
|
27
|
+
# change the SMTP host you simply need to do the following:
|
|
24
28
|
#
|
|
25
|
-
#
|
|
29
|
+
# Ramaze::Helper::Email.options.host = 'mail.google.com'
|
|
26
30
|
#
|
|
27
|
-
# Various other options are available, for a full list of these options run
|
|
28
|
-
# following in an IRB session:
|
|
31
|
+
# Various other options are available, for a full list of these options run
|
|
32
|
+
# the following in an IRB session:
|
|
29
33
|
#
|
|
30
|
-
#
|
|
34
|
+
# puts Ramaze::Helper::Email.options
|
|
31
35
|
#
|
|
32
|
-
# By default this helper uses
|
|
36
|
+
# By default this helper uses ``\r\n`` for newlines, this can be changed as
|
|
37
|
+
# following:
|
|
33
38
|
#
|
|
34
|
-
#
|
|
35
|
-
#
|
|
36
|
-
# It's important that this setting matches the settings of your SMTP server as
|
|
37
|
-
# otherwise you (usually) won't be able to send any Emails.
|
|
39
|
+
# Ramaze::Helper::Email.options.newline = "\n"
|
|
38
40
|
#
|
|
39
41
|
# @author Yorick Peterse
|
|
40
42
|
# @author Michael Fellinger
|
|
@@ -59,12 +61,12 @@ module Ramaze
|
|
|
59
61
|
"<" + Time.now.to_i.to_s + "@" + Ramaze::Helper::Email.options.helo_domain + ">"
|
|
60
62
|
}
|
|
61
63
|
end
|
|
62
|
-
|
|
64
|
+
|
|
63
65
|
##
|
|
64
66
|
# Sends an Email over SMTP.
|
|
65
67
|
#
|
|
66
68
|
# @example
|
|
67
|
-
# send_email('
|
|
69
|
+
# send_email('user@domain.tld', 'Hello, world!', 'Hello, this is an Email')
|
|
68
70
|
#
|
|
69
71
|
# @author Yorick Peterse
|
|
70
72
|
# @author Michael Fellinger
|
|
@@ -79,7 +81,7 @@ module Ramaze
|
|
|
79
81
|
id = Email.options.generator.call
|
|
80
82
|
|
|
81
83
|
# Generate the body of the Email
|
|
82
|
-
email
|
|
84
|
+
email = [
|
|
83
85
|
"From: #{sender}", "To: <#{recipient}>", "Date: #{Time.now.rfc2822}",
|
|
84
86
|
"Subject: #{subject}", "Message-Id: #{id}", '', message
|
|
85
87
|
].join(Email.options.newline)
|
|
@@ -93,11 +95,20 @@ module Ramaze
|
|
|
93
95
|
|
|
94
96
|
begin
|
|
95
97
|
Net::SMTP.start(*email_options) do |smtp|
|
|
96
|
-
smtp.send_message(
|
|
97
|
-
|
|
98
|
+
smtp.send_message(
|
|
99
|
+
email,
|
|
100
|
+
Email.options.sender,
|
|
101
|
+
[recipient, *Email.options.bcc]
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
Ramaze::Log.info(
|
|
105
|
+
"Email sent to #{recipient} with subject \"#{subject}\""
|
|
106
|
+
)
|
|
98
107
|
end
|
|
99
108
|
rescue => e
|
|
100
|
-
Ramaze::Log.error(
|
|
109
|
+
Ramaze::Log.error(
|
|
110
|
+
"Failed to send an Email to #{recipient}: #{e.inspect}"
|
|
111
|
+
)
|
|
101
112
|
end
|
|
102
113
|
end
|
|
103
114
|
end # Email
|
|
@@ -8,7 +8,7 @@ module Ramaze
|
|
|
8
8
|
##
|
|
9
9
|
# Allows you to use some shortcuts for Erector in your Controller.
|
|
10
10
|
#
|
|
11
|
-
# use this inside your controller to directly build Erector
|
|
11
|
+
# use this inside your controller to directly build Erector
|
|
12
12
|
# Refer to the Erector-documentation and testsuite for more examples.
|
|
13
13
|
#
|
|
14
14
|
# @example
|
|
@@ -26,19 +26,18 @@ module Ramaze
|
|
|
26
26
|
# Method that generates a XHTML 1.0 Strict doctype.
|
|
27
27
|
#
|
|
28
28
|
# @example
|
|
29
|
-
#
|
|
30
29
|
# strict_html do
|
|
31
30
|
# head do
|
|
32
31
|
# title "Ramaze Rocks!"
|
|
33
32
|
# end
|
|
34
33
|
# body
|
|
35
34
|
# div do
|
|
36
|
-
#
|
|
35
|
+
#
|
|
37
36
|
# end
|
|
38
37
|
# end
|
|
39
38
|
# end
|
|
40
39
|
#
|
|
41
|
-
# @param [Hash] args Hash containing extra options such as the xml:lang
|
|
40
|
+
# @param [Hash] args Hash containing extra options such as the xml:lang
|
|
42
41
|
# and xmlns attribute.
|
|
43
42
|
# @param [Block] block Block that contains the inner data of the <html>
|
|
44
43
|
# element.
|
|
@@ -53,7 +52,6 @@ module Ramaze
|
|
|
53
52
|
# Generate a Javascript tag.
|
|
54
53
|
#
|
|
55
54
|
# @example
|
|
56
|
-
#
|
|
57
55
|
# js 'javascript/jquery.js'
|
|
58
56
|
#
|
|
59
57
|
# @param [String] src The full or relative path to the Javascript file.
|
|
@@ -66,13 +64,12 @@ module Ramaze
|
|
|
66
64
|
# Generate a pair of conditional tags for a specific browser.
|
|
67
65
|
#
|
|
68
66
|
# @example
|
|
69
|
-
#
|
|
70
67
|
# ie_if 'IE' do
|
|
71
68
|
# ......
|
|
72
69
|
# end
|
|
73
70
|
#
|
|
74
71
|
# @param [String] expr The if expression, such as 'IE' or 'lte IE7'.
|
|
75
|
-
# @param [block] block Block that contains the data that needs to be
|
|
72
|
+
# @param [block] block Block that contains the data that needs to be
|
|
76
73
|
# loaded for the specified browser.
|
|
77
74
|
#
|
|
78
75
|
def ie_if(expr, &block)
|
|
@@ -94,19 +91,18 @@ module Ramaze
|
|
|
94
91
|
# Generate a stylesheet tag.
|
|
95
92
|
#
|
|
96
93
|
# @example
|
|
97
|
-
#
|
|
98
94
|
# css 'css/reset.css', :media => 'print'
|
|
99
95
|
#
|
|
100
|
-
# @param [String] href The path (either absolute or relative) to the CSS
|
|
96
|
+
# @param [String] href The path (either absolute or relative) to the CSS
|
|
101
97
|
# file.
|
|
102
|
-
# @param [Hash] args A hash containing additional arguments to add to
|
|
98
|
+
# @param [Hash] args A hash containing additional arguments to add to
|
|
103
99
|
# the CSS tag.
|
|
104
100
|
#
|
|
105
101
|
def css(href, args = {})
|
|
106
102
|
attrs = {
|
|
107
|
-
:rel => "stylesheet",
|
|
108
|
-
:href => href,
|
|
109
|
-
:type => "text/css"
|
|
103
|
+
:rel => "stylesheet",
|
|
104
|
+
:href => href,
|
|
105
|
+
:type => "text/css"
|
|
110
106
|
}.merge(args)
|
|
111
107
|
|
|
112
108
|
link attrs
|
data/lib/ramaze/helper/flash.rb
CHANGED
|
@@ -9,16 +9,14 @@ module Ramaze
|
|
|
9
9
|
# Flash is a way to keep a temporary pairs of keys and values for the duration
|
|
10
10
|
# of two requests, the current and following.
|
|
11
11
|
#
|
|
12
|
-
#
|
|
12
|
+
# Time for an example. On the first request, for example on registering:
|
|
13
13
|
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
# flash[:error] = "You should reconsider your username, it's taken already"
|
|
17
|
-
# redirect r(:register)
|
|
14
|
+
# flash[:error] = "You should reconsider your username, it's taken already"
|
|
15
|
+
# redirect r(:register)
|
|
18
16
|
#
|
|
19
17
|
# This is the request from the redirect:
|
|
20
18
|
#
|
|
21
|
-
#
|
|
19
|
+
# do_stuff if flash[:error]
|
|
22
20
|
#
|
|
23
21
|
# On the request after this, flash[:error] is gone.
|
|
24
22
|
|
|
@@ -59,6 +57,6 @@ module Ramaze
|
|
|
59
57
|
end
|
|
60
58
|
}.flatten.join("\n")
|
|
61
59
|
end
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
end
|
|
60
|
+
end # Flash
|
|
61
|
+
end # Helper
|
|
62
|
+
end # Ramaze
|
|
@@ -2,191 +2,206 @@
|
|
|
2
2
|
# All files in this distribution are subject to the terms of the Ruby license.
|
|
3
3
|
|
|
4
4
|
module Ramaze
|
|
5
|
-
module Helper
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def number_format(n, delimiter = ',')
|
|
43
|
-
delim_l, delim_r = delimiter == ',' ? %w[, .] : %w[. ,]
|
|
44
|
-
h, r = n.to_s.split('.')
|
|
45
|
-
[h.reverse.scan(/\d{1,3}/).join(delim_l).reverse, r].compact.join(delim_r)
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
# Answer with the ordinal version of a number.
|
|
49
|
-
#
|
|
50
|
-
# Usage:
|
|
51
|
-
# ordinal(1) # => "1st"
|
|
52
|
-
# ordinal(2) # => "2nd"
|
|
53
|
-
# ordinal(3) # => "3rd"
|
|
54
|
-
# ordinal(13) # => "13th"
|
|
55
|
-
# ordinal(33) # => "33rd"
|
|
56
|
-
# ordinal(100) # => "100th"
|
|
57
|
-
# ordinal(133) # => "133rd"
|
|
58
|
-
|
|
59
|
-
def ordinal(number)
|
|
60
|
-
number = number.to_i
|
|
61
|
-
|
|
62
|
-
case number % 100
|
|
63
|
-
when 11..13; "#{number}th"
|
|
64
|
-
else
|
|
65
|
-
case number % 10
|
|
66
|
-
when 1; "#{number}st"
|
|
67
|
-
when 2; "#{number}nd"
|
|
68
|
-
when 3; "#{number}rd"
|
|
69
|
-
else "#{number}th"
|
|
5
|
+
module Helper
|
|
6
|
+
module Formatting
|
|
7
|
+
module_function
|
|
8
|
+
|
|
9
|
+
FORMATTING_NUMBER_COUNTER = {
|
|
10
|
+
0 => 'no',
|
|
11
|
+
2 => 'two',
|
|
12
|
+
3 => 'three',
|
|
13
|
+
4 => 'four',
|
|
14
|
+
5 => 'five',
|
|
15
|
+
6 => 'six',
|
|
16
|
+
7 => 'seven',
|
|
17
|
+
8 => 'eight',
|
|
18
|
+
9 => 'nine',
|
|
19
|
+
10 => 'ten'
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
# Answers with a representation of given +count+ with correct grammar. If
|
|
23
|
+
# no +items+ argument is given, and the +count+ argument is not 1, then we
|
|
24
|
+
# first check whether the +item+ argument responds to ``#pluralize`` (for
|
|
25
|
+
# example if you are using Sequel). If this doesn't work we append 's'
|
|
26
|
+
# to the +item+ argument.
|
|
27
|
+
#
|
|
28
|
+
# @example usage
|
|
29
|
+
# number_counter(0, 'comment') # => 'no comments'
|
|
30
|
+
# number_counter(1, 'comment') # => 'one comment'
|
|
31
|
+
# number_counter(2, 'comment') # => '2 comments'
|
|
32
|
+
#
|
|
33
|
+
def number_counter(count, item, items = nil)
|
|
34
|
+
count, item = count.to_i, item.to_s
|
|
35
|
+
|
|
36
|
+
if count == 1
|
|
37
|
+
"one #{item}"
|
|
38
|
+
else
|
|
39
|
+
items ||= item.respond_to?(:pluralize) ? item.pluralize : "#{item}s"
|
|
40
|
+
prefix = FORMATTING_NUMBER_COUNTER[count] || count
|
|
41
|
+
"#{prefix} #{items}"
|
|
70
42
|
end
|
|
71
43
|
end
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
# stolen and adapted from rails
|
|
75
|
-
def time_diff(from_time, to_time = Time.now, include_seconds = false)
|
|
76
|
-
distance_in_minutes = (((to_time - from_time).abs)/60).round
|
|
77
|
-
distance_in_seconds = ((to_time - from_time).abs).round if include_seconds
|
|
78
|
-
|
|
79
|
-
case distance_in_minutes
|
|
80
|
-
when 0..1
|
|
81
|
-
return (distance_in_minutes == 0) ? 'less than a minute' : '1 minute' unless include_seconds
|
|
82
|
-
case distance_in_seconds
|
|
83
|
-
when 0..4 then 'less than 5 seconds'
|
|
84
|
-
when 5..9 then 'less than 10 seconds'
|
|
85
|
-
when 10..19 then 'less than 20 seconds'
|
|
86
|
-
when 20..39 then 'half a minute'
|
|
87
|
-
when 40..59 then 'less than a minute'
|
|
88
|
-
else '1 minute'
|
|
89
|
-
end
|
|
90
44
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
45
|
+
# Format a floating number nicely for display.
|
|
46
|
+
#
|
|
47
|
+
# @example
|
|
48
|
+
# number_format(123.123) # => '123.123'
|
|
49
|
+
# number_format(123456.12345) # => '123,456.12345'
|
|
50
|
+
# number_format(123456.12345, '.') # => '123.456,12345'
|
|
51
|
+
#
|
|
52
|
+
def number_format(n, delimiter = ',')
|
|
53
|
+
delim_l, delim_r = delimiter == ',' ? %w[, .] : %w[. ,]
|
|
54
|
+
h, r = n.to_s.split('.')
|
|
55
|
+
[h.reverse.scan(/\d{1,3}/).join(delim_l).reverse, r].compact.join(delim_r)
|
|
100
56
|
end
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
(
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
)
|
|
110
|
-
(
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
)
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
(?:/(?:[~\w\+@%=\(\)-]|(?:[,.;:'][^\s<$]))*)* # path
|
|
119
|
-
(?:\?[\w\+@%&=.;:-]+)? # query string
|
|
120
|
-
(?:\#[\w\-]*)? # trailing anchor
|
|
121
|
-
)
|
|
122
|
-
([[:punct:]]|<|$|) # trailing text
|
|
123
|
-
}x unless defined? AUTO_LINK_RE
|
|
124
|
-
|
|
125
|
-
# Turns all urls into clickable links. If a block is given, each url
|
|
126
|
-
# is yielded and the result is used as the link text.
|
|
127
|
-
def auto_link(text, opts = {})
|
|
128
|
-
html_options = ' ' + opts.map{|k,v| "#{k}='#{v}'"}.join(' ') if opts.any?
|
|
129
|
-
text.gsub(AUTO_LINK_RE) do
|
|
130
|
-
all, a, b, c, d = $&, $1, $2, $3, $4
|
|
131
|
-
if a =~ /<a\s/i # don't replace URL's that are already linked
|
|
132
|
-
all
|
|
57
|
+
|
|
58
|
+
# Answer with the ordinal version of a number.
|
|
59
|
+
#
|
|
60
|
+
# @example
|
|
61
|
+
# ordinal(1) # => "1st"
|
|
62
|
+
# ordinal(2) # => "2nd"
|
|
63
|
+
# ordinal(3) # => "3rd"
|
|
64
|
+
# ordinal(13) # => "13th"
|
|
65
|
+
# ordinal(33) # => "33rd"
|
|
66
|
+
# ordinal(100) # => "100th"
|
|
67
|
+
# ordinal(133) # => "133rd"
|
|
68
|
+
#
|
|
69
|
+
def ordinal(number)
|
|
70
|
+
number = number.to_i
|
|
71
|
+
|
|
72
|
+
case number % 100
|
|
73
|
+
when 11..13; "#{number}th"
|
|
133
74
|
else
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
75
|
+
case number % 10
|
|
76
|
+
when 1; "#{number}st"
|
|
77
|
+
when 2; "#{number}nd"
|
|
78
|
+
when 3; "#{number}rd"
|
|
79
|
+
else "#{number}th"
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# stolen and adapted from rails
|
|
85
|
+
def time_diff(from_time, to_time = Time.now, include_seconds = false)
|
|
86
|
+
distance_in_minutes = (((to_time - from_time).abs)/60).round
|
|
87
|
+
distance_in_seconds = ((to_time - from_time).abs).round if include_seconds
|
|
88
|
+
|
|
89
|
+
case distance_in_minutes
|
|
90
|
+
when 0..1
|
|
91
|
+
return (distance_in_minutes == 0) ? 'less than a minute' : '1 minute' unless include_seconds
|
|
92
|
+
case distance_in_seconds
|
|
93
|
+
when 0..4 then 'less than 5 seconds'
|
|
94
|
+
when 5..9 then 'less than 10 seconds'
|
|
95
|
+
when 10..19 then 'less than 20 seconds'
|
|
96
|
+
when 20..39 then 'half a minute'
|
|
97
|
+
when 40..59 then 'less than a minute'
|
|
98
|
+
else '1 minute'
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
when 2..44 then "#{distance_in_minutes} minutes"
|
|
102
|
+
when 45..89 then 'about 1 hour'
|
|
103
|
+
when 90..1439 then "about #{(distance_in_minutes.to_f / 60.0).round} hours"
|
|
104
|
+
when 1440..2879 then '1 day'
|
|
105
|
+
when 2880..43199 then "#{(distance_in_minutes / 1440).round} days"
|
|
106
|
+
when 43200..86399 then 'about 1 month'
|
|
107
|
+
when 86400..525959 then "#{(distance_in_minutes / 43200).round} months"
|
|
108
|
+
when 525960..1051919 then 'about 1 year'
|
|
109
|
+
else "over #{(distance_in_minutes / 525960).round} years"
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Copied from actionpack, and revised by insane-dreamer to fix a bug
|
|
114
|
+
# (original fails on some URLs)
|
|
115
|
+
AUTO_LINK_RE = %r{
|
|
116
|
+
( # leading text
|
|
117
|
+
<\w+.*?>| # leading HTML tag, or
|
|
118
|
+
[^=!:'"/]| # leading punctuation, or
|
|
119
|
+
^ # beginning of line
|
|
120
|
+
)
|
|
121
|
+
(
|
|
122
|
+
(?:https?://)| # protocol spec, or
|
|
123
|
+
(?:www\.) # www.*
|
|
124
|
+
)
|
|
125
|
+
(
|
|
126
|
+
[-\w]+ # subdomain or domain
|
|
127
|
+
(?:\.[-\w]+)* # remaining subdomains or domain
|
|
128
|
+
(?::\d+)? # port
|
|
129
|
+
(?:/(?:[~\w\+@%=\(\)-]|(?:[,.;:'][^\s<$]))*)* # path
|
|
130
|
+
(?:\?[\w\+@%&=.;:-]+)? # query string
|
|
131
|
+
(?:\#[\w\-]*)? # trailing anchor
|
|
132
|
+
)
|
|
133
|
+
([[:punct:]]|<|$|) # trailing text
|
|
134
|
+
}x unless defined? AUTO_LINK_RE
|
|
135
|
+
|
|
136
|
+
# Turns all urls into clickable links. If a block is given, each url
|
|
137
|
+
# is yielded and the result is used as the link text.
|
|
138
|
+
def auto_link(text, opts = {})
|
|
139
|
+
html_options = ' ' + opts.map{|k,v| "#{k}='#{v}'"}.join(' ') if opts.any?
|
|
140
|
+
text.gsub(AUTO_LINK_RE) do
|
|
141
|
+
all, a, b, c, d = $&, $1, $2, $3, $4
|
|
142
|
+
if a =~ /<a\s/i # don't replace URL's that are already linked
|
|
143
|
+
all
|
|
144
|
+
else
|
|
145
|
+
text = b + c
|
|
146
|
+
text = yield(text) if block_given?
|
|
147
|
+
%(#{a}<a href="#{b=="www."?"http://www.":b}#{c}"#{html_options}>#{text}</a>#{d})
|
|
148
|
+
end
|
|
137
149
|
end
|
|
138
150
|
end
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
# Maybe port to ruby < 1.8.7 ?
|
|
152
|
-
def obfuscate_email(email, text = nil)
|
|
153
|
-
obfuscated = []
|
|
154
|
-
email.to_s.each_byte{|c| obfuscated << "&#%03d" % c }
|
|
155
|
-
joined = obfuscated.join
|
|
156
|
-
|
|
157
|
-
%(<a href="mailto:#{joined}">#{text || joined}</a>)
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
# Returns Hash with tags as keys and their weight as value.
|
|
161
|
-
#
|
|
162
|
-
# Example:
|
|
163
|
-
# tags = %w[ruby ruby code ramaze]
|
|
164
|
-
# tagcloud(tags)
|
|
165
|
-
# # => {"code"=>0.75, "ramaze"=>0.75, "ruby"=>1.0}
|
|
166
|
-
#
|
|
167
|
-
# The weight can be influenced by adjusting the +min+ and +max+ parameters,
|
|
168
|
-
# please make sure that +max+ is larger than +min+ to get meaningful output.
|
|
169
|
-
#
|
|
170
|
-
# This is not thought as immediate output to your template but rather to
|
|
171
|
-
# help either implementing your own algorithm or using the result as input
|
|
172
|
-
# for your tagcloud.
|
|
173
|
-
#
|
|
174
|
-
# Example:
|
|
175
|
-
# - tagcloud(tags).each do |tag, weight|
|
|
176
|
-
# - style = "font-size: %0.2fem" % weight
|
|
177
|
-
# %a{:style => style, :href => Rs(tag)}= h(tag)
|
|
178
|
-
|
|
179
|
-
def tagcloud(tags, min = 0.5, max = 1.5)
|
|
180
|
-
result = {}
|
|
181
|
-
total = tags.size.to_f
|
|
182
|
-
diff = max - min
|
|
183
|
-
|
|
184
|
-
tags.uniq.each do |tag|
|
|
185
|
-
count = tags.respond_to?(:count) ? tags.count(tag) : tags.select{|t| t==tag }.size
|
|
186
|
-
result[tag] = ((count / total) * diff) + min
|
|
151
|
+
alias autolink auto_link
|
|
152
|
+
|
|
153
|
+
# takes a string and optional argument for outputting compliance HTML
|
|
154
|
+
# instead of XHTML.
|
|
155
|
+
#
|
|
156
|
+
# @example
|
|
157
|
+
# nl2br "a\nb\n\c" #=> 'a<br />b<br />c'
|
|
158
|
+
#
|
|
159
|
+
def nl2br(string, xhtml = true)
|
|
160
|
+
br = xhtml ? '<br />' : '<br>'
|
|
161
|
+
string.gsub(/\n/, br)
|
|
187
162
|
end
|
|
188
163
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
164
|
+
def obfuscate_email(email, text = nil)
|
|
165
|
+
obfuscated = []
|
|
166
|
+
email.to_s.each_byte{|c| obfuscated << "&#%03d" % c }
|
|
167
|
+
joined = obfuscated.join
|
|
168
|
+
|
|
169
|
+
%(<a href="mailto:#{joined}">#{text || joined}</a>)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# Returns Hash with tags as keys and their weight as value.
|
|
173
|
+
#
|
|
174
|
+
# Example:
|
|
175
|
+
# tags = %w[ruby ruby code ramaze]
|
|
176
|
+
# tagcloud(tags)
|
|
177
|
+
# # => {"code"=>0.75, "ramaze"=>0.75, "ruby"=>1.0}
|
|
178
|
+
#
|
|
179
|
+
# The weight can be influenced by adjusting the +min+ and +max+
|
|
180
|
+
# parameters, please make sure that +max+ is larger than +min+ to get
|
|
181
|
+
# meaningful output.
|
|
182
|
+
#
|
|
183
|
+
# This is not thought as immediate output to your template but rather to
|
|
184
|
+
# help either implementing your own algorithm or using the result as input
|
|
185
|
+
# for your tagcloud.
|
|
186
|
+
#
|
|
187
|
+
# @example
|
|
188
|
+
# tagcloud(tags).each do |tag, weight|
|
|
189
|
+
# style = "font-size: %0.2fem" % weight
|
|
190
|
+
# %a{:style => style, :href => Rs(tag)}= h(tag)
|
|
191
|
+
# end
|
|
192
|
+
#
|
|
193
|
+
def tagcloud(tags, min = 0.5, max = 1.5)
|
|
194
|
+
result = {}
|
|
195
|
+
total = tags.size.to_f
|
|
196
|
+
diff = max - min
|
|
197
|
+
|
|
198
|
+
tags.uniq.each do |tag|
|
|
199
|
+
count = tags.respond_to?(:count) ? tags.count(tag) : tags.select{|t| t==tag }.size
|
|
200
|
+
result[tag] = ((count / total) * diff) + min
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
result
|
|
204
|
+
end
|
|
205
|
+
end # Formatting
|
|
206
|
+
end # Helper
|
|
207
|
+
end # Ramaze
|