ramaze 2010.06.18 → 2011.01
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/MANIFEST +9 -16
- data/README.md +37 -30
- data/Rakefile +5 -1
- data/TODO.md +19 -0
- data/doc/AUTHORS +5 -1
- data/doc/CHANGELOG +3553 -3272
- data/doc/tutorial/todolist.html +1512 -1512
- data/examples/app/blog/app.rb +2 -0
- data/examples/app/todolist/controller/init.rb +1 -2
- data/examples/app/wiktacular/mkd/main/2007-07-20_19-21-12.mkd +1 -1
- data/examples/app/wiktacular/mkd/main/2007-07-20_19-23-10.mkd +1 -1
- data/examples/app/wiktacular/mkd/main/2007-07-20_19-45-07.mkd +1 -1
- data/examples/app/wiktacular/mkd/main/current.mkd +1 -1
- data/examples/app/wiktacular/mkd/testing/2007-07-20_16-43-46.mkd +1 -1
- data/examples/app/wiktacular/mkd/testing/2007-07-20_19-43-50.mkd +2 -2
- data/examples/app/wiktacular/mkd/testing/2007-07-21_18-47-08.mkd +16 -16
- data/examples/app/wiktacular/mkd/testing/2007-07-21_18-47-54.mkd +16 -16
- data/examples/app/wiktacular/mkd/testing/current.mkd +16 -16
- data/lib/proto/model/init.rb +1 -1
- data/lib/proto/public/js/jquery.js +2034 -1095
- data/lib/proto/start.rb +2 -0
- data/lib/proto/view/index.xhtml +3 -3
- data/lib/ramaze.rb +1 -2
- data/lib/ramaze/cache.rb +1 -0
- data/lib/ramaze/cache/sequel.rb +131 -37
- data/lib/ramaze/controller.rb +1 -0
- data/lib/ramaze/gestalt.rb +75 -46
- data/lib/ramaze/helper.rb +1 -0
- data/lib/ramaze/helper/auth.rb +38 -4
- data/lib/ramaze/helper/blue_form.rb +498 -78
- data/lib/ramaze/helper/cache.rb +2 -2
- data/lib/ramaze/helper/csrf.rb +225 -0
- data/lib/ramaze/helper/erector.rb +67 -9
- data/lib/ramaze/helper/flash.rb +4 -2
- data/lib/ramaze/helper/gestalt.rb +2 -0
- data/lib/ramaze/helper/gravatar.rb +1 -1
- data/lib/ramaze/helper/localize.rb +4 -0
- data/lib/ramaze/helper/send_file.rb +30 -0
- data/lib/ramaze/helper/thread.rb +5 -0
- data/lib/ramaze/helper/user.rb +4 -3
- data/lib/ramaze/helper/xhtml.rb +87 -8
- data/lib/ramaze/log.rb +13 -0
- data/lib/ramaze/log/analogger.rb +15 -5
- data/lib/ramaze/log/growl.rb +28 -13
- data/lib/ramaze/log/hub.rb +12 -4
- data/lib/ramaze/log/informer.rb +28 -11
- data/lib/ramaze/log/knotify.rb +7 -2
- data/lib/ramaze/log/logger.rb +12 -4
- data/lib/ramaze/log/logging.rb +40 -14
- data/lib/ramaze/log/rotatinginformer.rb +47 -23
- data/lib/ramaze/log/syslog.rb +37 -31
- data/lib/ramaze/log/xosd.rb +7 -4
- data/lib/ramaze/middleware_compiler.rb +2 -2
- data/lib/ramaze/snippets/fiber.rb +63 -63
- data/lib/ramaze/snippets/ramaze/lru_hash.rb +1 -1
- data/lib/ramaze/tool/bin.rb +1 -1
- data/lib/ramaze/version.rb +1 -1
- data/lib/ramaze/view.rb +4 -4
- data/lib/ramaze/view/erector.rb +88 -13
- data/ramaze.gemspec +65 -65
- data/spec/ramaze/bin/ramaze.rb +1 -1
- data/spec/ramaze/cache/localmemcache.rb +20 -12
- data/spec/ramaze/cache/sequel.rb +19 -19
- data/spec/ramaze/helper/blue_form.rb +549 -257
- data/spec/ramaze/helper/csrf.rb +109 -0
- data/spec/ramaze/helper/httpdigest.rb +31 -29
- data/spec/ramaze/helper/user.rb +1 -1
- data/spec/ramaze/helper/xhtml.rb +17 -0
- data/spec/ramaze/log/growl.rb +34 -0
- data/spec/ramaze/log/informer.rb +1 -0
- data/spec/ramaze/view/erector.rb +49 -71
- data/spec/ramaze/view/erector/external_view.erector +5 -0
- data/spec/ramaze/view/erector/index.erector +5 -0
- data/spec/ramaze/view/erector/layout.erector +13 -3
- data/spec/ramaze/view/erector/tables.erector +23 -0
- data/spec/ramaze/view/erector/view.erector +6 -0
- data/tasks/git.rake +2 -2
- metadata +133 -176
- data/examples/helpers/form_with_sequel.rb +0 -24
- data/examples/helpers/nitro_form.rb +0 -23
- data/lib/ramaze/helper/form.rb +0 -133
- data/lib/ramaze/helper/nitroform.rb +0 -14
- data/lib/ramaze/helper/pager.rb +0 -367
- data/lib/ramaze/helper/partial.rb +0 -100
- data/lib/ramaze/helper/sequel.rb +0 -55
- data/lib/ramaze/helper/sequel_form.rb +0 -284
- data/lib/vendor/etag.rb +0 -22
- data/spec/ramaze/helper/form.rb +0 -360
- data/spec/ramaze/helper/pager.rb +0 -96
- data/spec/ramaze/helper/sequel_form.rb +0 -94
- data/spec/ramaze/view/erector/external.erector +0 -1
- data/spec/ramaze/view/erector/invoke_helper_method.erector +0 -1
- data/spec/ramaze/view/erector/strict_xhtml.erector +0 -3
- data/spec/ramaze/view/erector/sum.erector +0 -1
data/lib/ramaze/helper.rb
CHANGED
data/lib/ramaze/helper/auth.rb
CHANGED
@@ -8,6 +8,13 @@ module Ramaze
|
|
8
8
|
# Please have a look at the docs of Auth#auth_login.
|
9
9
|
#
|
10
10
|
# If you want to do authentication with a model see Helper::User instead.
|
11
|
+
|
12
|
+
##
|
13
|
+
# The Auth helper can be used for authentication without using a model.
|
14
|
+
# This can be useful when working with very basic applications that don't require database access.
|
15
|
+
#
|
16
|
+
# If you're looking for a way to do authentication using a model you should take a look at Helper::User instead.
|
17
|
+
#
|
11
18
|
module Auth
|
12
19
|
Helper::LOOKUP << self
|
13
20
|
include Ramaze::Traited
|
@@ -19,7 +26,12 @@ module Ramaze
|
|
19
26
|
def self.included(into)
|
20
27
|
into.helper(:stack)
|
21
28
|
end
|
22
|
-
|
29
|
+
|
30
|
+
##
|
31
|
+
# Log a user in based on the :username and :password key in the request hash.
|
32
|
+
#
|
33
|
+
# @return [String] The login template in case the user's login data was incorrect.
|
34
|
+
#
|
23
35
|
def login
|
24
36
|
return auth_template if trait[:auth_post_only] and !request.post?
|
25
37
|
@username, password = request[:username, :password]
|
@@ -27,6 +39,9 @@ module Ramaze
|
|
27
39
|
return auth_template
|
28
40
|
end
|
29
41
|
|
42
|
+
##
|
43
|
+
# Log the user out and redirect him back to the previous page.
|
44
|
+
#
|
30
45
|
def logout
|
31
46
|
auth_logout
|
32
47
|
answer(request.referer)
|
@@ -34,16 +49,29 @@ module Ramaze
|
|
34
49
|
|
35
50
|
private
|
36
51
|
|
52
|
+
##
|
53
|
+
# Validate the user's session and redirect him/her to the login page in case the user isn't logged in.
|
54
|
+
#
|
37
55
|
def login_required
|
38
56
|
call(r(:login)) unless logged_in?
|
39
57
|
end
|
40
58
|
|
41
|
-
|
59
|
+
##
|
60
|
+
# Validate the user's session and return a boolean that indicates if the user is logged in or not.
|
61
|
+
#
|
62
|
+
# @return [true false] Whether user is logged in right now
|
63
|
+
#
|
42
64
|
def logged_in?
|
43
65
|
!!session[:logged_in]
|
44
66
|
end
|
45
67
|
|
46
|
-
|
68
|
+
##
|
69
|
+
# Try to log the user in based on the username and password.
|
70
|
+
# This method is called by the login() method and shouldn't be called directly.
|
71
|
+
#
|
72
|
+
# @param [String] user The users's username.
|
73
|
+
# @param [String] pass The user's password.
|
74
|
+
#
|
47
75
|
def auth_login(user, pass)
|
48
76
|
return unless user and pass
|
49
77
|
return if user.empty? or pass.empty?
|
@@ -62,12 +90,18 @@ module Ramaze
|
|
62
90
|
session[:username] = user
|
63
91
|
end
|
64
92
|
|
93
|
+
##
|
94
|
+
# Remove the session items that specified that the user was logged in.
|
95
|
+
#
|
65
96
|
def auth_logout
|
66
97
|
session.delete(:logged_in)
|
67
98
|
session.delete(:username)
|
68
99
|
end
|
69
100
|
|
70
|
-
|
101
|
+
##
|
102
|
+
# Method that returns a small form that can be used for logging in.
|
103
|
+
#
|
104
|
+
# @return [String] The login form.
|
71
105
|
def auth_template
|
72
106
|
<<-TEMPLATE.strip!
|
73
107
|
<form method="post" action="#{r(:login)}">
|
@@ -3,15 +3,90 @@ require 'ramaze/gestalt'
|
|
3
3
|
|
4
4
|
module Ramaze
|
5
5
|
module Helper
|
6
|
-
|
7
|
-
#
|
6
|
+
##
|
7
|
+
# == Introduction
|
8
|
+
#
|
9
|
+
# The BlueForm helper tries to be an even better way to build forms programmatically.
|
10
|
+
# By using a simple block you can quickly create all the required elements for your form.
|
11
|
+
#
|
12
|
+
# Since November 2010 the BlueForm helper works different. You can now specify an object as the first
|
13
|
+
# parameter of the form_for() method. This object will be used to retrieve the values of each field.
|
14
|
+
# This means that you can directly pass a database result object to the form and no longer have
|
15
|
+
# to manually specify values. However, you can still specify your own values if you want.
|
16
|
+
#
|
17
|
+
# Old behaviour:
|
18
|
+
#
|
19
|
+
# form_for(:method => :post) do |f|
|
20
|
+
# f.input_text 'Username', :username, 'Chuck Norris'
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# New behaviour:
|
24
|
+
#
|
25
|
+
# # @data is an object that contains an instance variable named "username".
|
26
|
+
# # This variable contains the value "Chuck Norris".
|
27
|
+
# form_for(@data, :method => :post) do |f|
|
28
|
+
# f.input_text 'Username', :username
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# == Form Data
|
32
|
+
#
|
33
|
+
# As stated earlier it's possible to pass an object to the form_for() method. What kind of object this is,
|
34
|
+
# a database result object or an OpenStruct object doesn't matter as long as the attributes can be accessed
|
35
|
+
# outside of the object (this can be done using attr_readers). This makes it extremely easy to directly pass
|
36
|
+
# a result object from your favourite ORM. Example:
|
37
|
+
#
|
38
|
+
# @data = User[1]
|
39
|
+
#
|
40
|
+
# form_for(@data, :method => :post) do |f|
|
41
|
+
# f.input_text 'Username', :username
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
# If you don't want to use an object you can simply set the first parameter to nil.
|
45
|
+
#
|
46
|
+
# == HTML Output
|
47
|
+
#
|
48
|
+
# The form helper uses Gestalt, Ramaze's custom HTML builder that works somewhat like Erector.
|
49
|
+
# The output is very minimalistic, elements such as legends and fieldsets have to be added manually.
|
50
|
+
# Each combination of a label and input element will be wrapped in <p> tags.
|
51
|
+
#
|
52
|
+
# When using the form helper as a block in your templates it's important to remember that the
|
53
|
+
# result is returned and not displayed in the browser directly. When using Etanni this would result in
|
54
|
+
# something like the following:
|
55
|
+
#
|
56
|
+
# #{
|
57
|
+
# form_for(@result, :method => :post) do |f| do
|
58
|
+
# f.input_text 'Text label', :textname, 'Chunky bacon!'
|
59
|
+
# end
|
60
|
+
# }
|
61
|
+
#
|
62
|
+
# @example
|
63
|
+
#
|
64
|
+
# form_for(@data, :method => :post) do |f|
|
65
|
+
# f.input_text 'Username', :username
|
66
|
+
# end
|
67
|
+
#
|
8
68
|
module BlueForm
|
9
|
-
|
10
|
-
|
69
|
+
##
|
70
|
+
# The form method generates the basic structure of the form. It should be called
|
71
|
+
# using a block and it's return value should be manually sent to the browser (since it does not echo the value).
|
72
|
+
#
|
73
|
+
# @param [Object] form_values Object containing the values for each form field.
|
74
|
+
# @param [Hash] options Hash containing any additional form attributes such as the method, action, enctype and so on.
|
75
|
+
# @param [Block] block Block containing the elements of the form such as password fields, textareas and so on.
|
76
|
+
#
|
77
|
+
def form_for(form_values, options = {}, &block)
|
78
|
+
form = Form.new(form_values, options)
|
11
79
|
form.build(form_errors, &block)
|
12
80
|
form
|
13
81
|
end
|
14
82
|
|
83
|
+
##
|
84
|
+
# Manually add a new error to the form_errors key in the flash hash.
|
85
|
+
# The first parameter is the name of the form field and the second parameter is the custom message.
|
86
|
+
#
|
87
|
+
# @param [String] name The name of the form field to which the error belongs.
|
88
|
+
# @param [String] message The custom error message to show.
|
89
|
+
#
|
15
90
|
def form_error(name, message)
|
16
91
|
if respond_to?(:flash)
|
17
92
|
old = flash[:form_errors] || {}
|
@@ -21,6 +96,12 @@ module Ramaze
|
|
21
96
|
end
|
22
97
|
end
|
23
98
|
|
99
|
+
##
|
100
|
+
# Returns the hash containing all existing errors and allows other methods to set
|
101
|
+
# new errors by using this method as if it were a hash.
|
102
|
+
#
|
103
|
+
# @return [Array] All form errors.
|
104
|
+
#
|
24
105
|
def form_errors
|
25
106
|
if respond_to?(:flash)
|
26
107
|
flash[:form_errors] ||= {}
|
@@ -29,42 +110,122 @@ module Ramaze
|
|
29
110
|
end
|
30
111
|
end
|
31
112
|
|
113
|
+
##
|
114
|
+
# Retrieve all the form errors for the specified model and add them to the flash hash.
|
115
|
+
#
|
116
|
+
# @param [Object] obj An object of a model that contains form errors.
|
117
|
+
#
|
32
118
|
def form_errors_from_model(obj)
|
33
|
-
obj.errors
|
34
|
-
|
119
|
+
if obj.respond_to?(:errors)
|
120
|
+
obj.errors.each do |key, value|
|
121
|
+
if value.respond_to?(:first)
|
122
|
+
value = value.first
|
123
|
+
end
|
124
|
+
|
125
|
+
form_error(key.to_s, value % key)
|
126
|
+
end
|
35
127
|
end
|
36
128
|
end
|
37
129
|
|
38
|
-
|
39
|
-
#
|
130
|
+
##
|
131
|
+
# Main form class that contains all the required methods to generate form specific tags,
|
132
|
+
# such as textareas and select boxes. Do note that this class is not thread-safe so you should
|
133
|
+
# modify it only within one thread of execution.
|
134
|
+
#
|
40
135
|
class Form
|
41
136
|
attr_reader :g
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
137
|
+
attr_reader :form_values
|
138
|
+
|
139
|
+
##
|
140
|
+
# Constructor method that generates an instance of the Form class.
|
141
|
+
#
|
142
|
+
# @param [Object] form_values Object containing the values for each form field.
|
143
|
+
# @param [Hash] options A hash containing any additional form attributes.
|
144
|
+
# @return [Object] An instance of the Form class.
|
145
|
+
#
|
146
|
+
def initialize(form_values, options)
|
147
|
+
@form_values = form_values
|
148
|
+
@form_args = options.dup
|
149
|
+
@g = Gestalt.new
|
46
150
|
end
|
47
151
|
|
152
|
+
##
|
153
|
+
# Builds the form by generating the opening/closing tags and executing
|
154
|
+
# the methods in the block.
|
155
|
+
#
|
156
|
+
# @param [Hash] form_errors Hash containing all form errors (if any).
|
157
|
+
#
|
48
158
|
def build(form_errors = {})
|
49
|
-
|
50
|
-
|
159
|
+
# Convert all the keys in form_errors to strings and
|
160
|
+
# retrieve the correct values in case
|
161
|
+
@form_errors = {}
|
162
|
+
|
163
|
+
form_errors.each do |key, value|
|
164
|
+
if value.respond_to?(:first)
|
165
|
+
value = value.first
|
166
|
+
end
|
167
|
+
|
168
|
+
@form_errors[key.to_s] = value
|
169
|
+
end
|
170
|
+
|
51
171
|
@g.form(@form_args) do
|
52
172
|
if block_given?
|
53
|
-
|
54
|
-
yield self
|
55
|
-
end
|
173
|
+
yield self
|
56
174
|
end
|
57
175
|
end
|
58
176
|
end
|
59
177
|
|
178
|
+
##
|
179
|
+
# Generate a <legend> tag.
|
180
|
+
#
|
181
|
+
# @param [String] text The text to display inside the legend tag.
|
182
|
+
# @example
|
183
|
+
#
|
184
|
+
# form_for(@data, :method => :post) do |f|
|
185
|
+
# f.legend 'Ramaze rocks!'
|
186
|
+
# end
|
187
|
+
#
|
60
188
|
def legend(text)
|
61
189
|
@g.legend(text)
|
62
190
|
end
|
191
|
+
|
192
|
+
##
|
193
|
+
# Generate a fieldset tag.
|
194
|
+
#
|
195
|
+
# @param [Block] &block The form elements to display inside the fieldset.
|
196
|
+
# @example
|
197
|
+
#
|
198
|
+
# form_for(@data, :method => :post) do |f|
|
199
|
+
# f.fieldset do
|
200
|
+
# f.legend 'Hello, world!'
|
201
|
+
# end
|
202
|
+
# end
|
203
|
+
#
|
204
|
+
def fieldset(&block)
|
205
|
+
@g.fieldset(block)
|
206
|
+
end
|
63
207
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
208
|
+
##
|
209
|
+
# Generate an input tag with a type of "text" along with a label tag.
|
210
|
+
# This method also has the alias "text" so feel free to use that one instead of input_text.
|
211
|
+
#
|
212
|
+
# @param [String] label The text to display inside the label tag.
|
213
|
+
# @param [String Symbol] name The name of the text field.
|
214
|
+
# @param [Hash] args Any additional HTML attributes along with their values.
|
215
|
+
# @example
|
216
|
+
#
|
217
|
+
# form_for(@data, :method => :post) do |f|
|
218
|
+
# f.input_text 'Username', :username
|
219
|
+
# end
|
220
|
+
#
|
221
|
+
def input_text(label, name, args = {})
|
222
|
+
# The ID can come from 2 places, id_for and the args hash
|
223
|
+
id = args[:id] ? args[:id] : id_for(name)
|
224
|
+
args = args.merge(:type => :text, :name => name, :id => id)
|
225
|
+
|
226
|
+
if !args[:value] and @form_values.respond_to?(name)
|
227
|
+
args[:value] = @form_values.send(name)
|
228
|
+
end
|
68
229
|
|
69
230
|
@g.p do
|
70
231
|
label_for(id, label, name)
|
@@ -73,10 +234,29 @@ module Ramaze
|
|
73
234
|
end
|
74
235
|
alias text input_text
|
75
236
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
237
|
+
##
|
238
|
+
# Generate an input tag with a type of "password" along with a label.
|
239
|
+
# Password fields are pretty much the same as text fields except that the content of these fields is replaced with dots.
|
240
|
+
# This method has the following alias: "password".
|
241
|
+
#
|
242
|
+
# @param [String] label The text to display inside the label tag.
|
243
|
+
# @param [String Symbol] name The name of the password field.
|
244
|
+
# @param [Hash] args Any additional HTML attributes along with their values.
|
245
|
+
# @example
|
246
|
+
#
|
247
|
+
# form_for(@data, :method => :post) do |f|
|
248
|
+
# f.input_password 'My password', :password
|
249
|
+
# end
|
250
|
+
#
|
251
|
+
def input_password(label, name, args = {})
|
252
|
+
# The ID can come from 2 places, id_for and the args hash
|
253
|
+
id = args[:id] ? args[:id] : id_for(name)
|
254
|
+
args = args.merge(:type => :password, :name => name, :id => id)
|
255
|
+
|
256
|
+
if !args[:value] and @form_values.respond_to?(name)
|
257
|
+
args[:value] = @form_values.send(name)
|
258
|
+
end
|
259
|
+
|
80
260
|
@g.p do
|
81
261
|
label_for(id, label, name)
|
82
262
|
@g.input(args)
|
@@ -84,8 +264,20 @@ module Ramaze
|
|
84
264
|
end
|
85
265
|
alias password input_password
|
86
266
|
|
87
|
-
|
88
|
-
|
267
|
+
##
|
268
|
+
# Generate a submit tag (without a label). A submit tag is a button that once it's clicked
|
269
|
+
# will send the form data to the server.
|
270
|
+
#
|
271
|
+
# @param [String] value The text to display in the button.
|
272
|
+
# @param [Hash] args Any additional HTML attributes along with their values.
|
273
|
+
# @example
|
274
|
+
#
|
275
|
+
# form_for(@data, :method => :post) do |f|
|
276
|
+
# f.input_submit 'Save'
|
277
|
+
# end
|
278
|
+
#
|
279
|
+
def input_submit(value = nil, args = {})
|
280
|
+
args = args.merge(:type => :submit)
|
89
281
|
args[:value] = value unless value.nil?
|
90
282
|
|
91
283
|
@g.p do
|
@@ -94,49 +286,193 @@ module Ramaze
|
|
94
286
|
end
|
95
287
|
alias submit input_submit
|
96
288
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
289
|
+
##
|
290
|
+
# Generate an input tag with a type of "checkbox". This method will also
|
291
|
+
# generate a hidden field with the same name as the checkbox to ensure
|
292
|
+
# that the data is always submitted.
|
293
|
+
#
|
294
|
+
# If you want to have multiple checkboxes you can either use an array or a hash.
|
295
|
+
# In the case of an array the values will also be used as text for each checkbox.
|
296
|
+
# When using a hash the key will be displayed and the value will be the value of the
|
297
|
+
# checkbox. Example:
|
298
|
+
#
|
299
|
+
# @data = Class.new
|
300
|
+
# attr_reader :gender_arr
|
301
|
+
# attr_reader :gender_hash
|
302
|
+
#
|
303
|
+
# def initialize
|
304
|
+
# @gender_arr = ['male', 'female']
|
305
|
+
# @gender_hash = {"Male" => "male", "Female" => "female"}
|
306
|
+
# end
|
307
|
+
# end.new
|
308
|
+
#
|
309
|
+
# form_for(@data, :method => :post) do |f|
|
310
|
+
# f.input_checkbox "Gender", :gender_arr
|
311
|
+
# f.input_checkbox "Gender", :gender_hash
|
312
|
+
# end
|
313
|
+
#
|
314
|
+
# @param [String] label The text to display inside the label tag.
|
315
|
+
# @param [String Symbol] name The name of the checkbox.
|
316
|
+
# @param [String] checked String that indicates if (and which) checkbox should be checked.
|
317
|
+
# @param [Hash] args Any additional HTML attributes along with their values.
|
318
|
+
# @example
|
319
|
+
#
|
320
|
+
# form_for(@data, :method => :post) do |f|
|
321
|
+
# f.input_checkbox 'Remember me', :remember_user
|
322
|
+
# end
|
323
|
+
#
|
324
|
+
def input_checkbox(label, name, checked = nil, args = {})
|
325
|
+
id = args[:id] ? args[:id] : "#{id_for(name)}_0"
|
326
|
+
|
327
|
+
# Get the default value for the checkbox used for the hidden field.
|
328
|
+
if args[:default]
|
329
|
+
default = args[:default]
|
330
|
+
args.delete(:default)
|
331
|
+
else
|
332
|
+
default = 0
|
333
|
+
end
|
101
334
|
|
102
|
-
|
103
|
-
|
104
|
-
|
335
|
+
# Get the checkbox value from either the args hash or from
|
336
|
+
# the form object (as specified in the form_for() method).
|
337
|
+
if !args[:values] and @form_values.respond_to?(name)
|
338
|
+
args[:values] = @form_values.send(name)
|
339
|
+
end
|
340
|
+
|
341
|
+
# That class for each element wrapper (a span tag) can be customized
|
342
|
+
# using :span_class => "a_class".
|
343
|
+
if args[:span_class]
|
344
|
+
span_class = args[:span_class]
|
345
|
+
args.delete(:span_class)
|
346
|
+
else
|
347
|
+
span_class = "checkbox_wrap"
|
348
|
+
end
|
349
|
+
|
350
|
+
# Get the type from the args hash instead of pre-defining it. Doing so means we can use
|
351
|
+
# this method for the input_radio method.
|
352
|
+
if !args[:type]
|
353
|
+
args[:type] = :checkbox
|
354
|
+
end
|
355
|
+
|
356
|
+
# Convert the values to an array if it's something we can't use in a loop (e.g. a string).
|
357
|
+
if args[:values].class != Hash and args[:values].class != Array
|
358
|
+
args[:values] = [args[:values]]
|
359
|
+
end
|
360
|
+
|
361
|
+
# Create a checkbox for each value
|
362
|
+
if !args[:values].empty?
|
363
|
+
@g.p do
|
364
|
+
# Let's create the label and the hidden field
|
365
|
+
label_for(id, label, name)
|
366
|
+
self.input_hidden(name, default)
|
367
|
+
|
368
|
+
# Loop through all the values. Each checkbox will have an ID of "form-NAME-INDEX".
|
369
|
+
# Each name will be NAME followed by [] to indicate it's an array (since multiple values are possible).
|
370
|
+
args[:values].each_with_index do |value, index|
|
371
|
+
id = args[:id] ? args[:id] : "#{id_for(name)}_#{index}"
|
372
|
+
|
373
|
+
if args[:type] == :checkbox
|
374
|
+
checkbox_name = "#{name}[]"
|
375
|
+
else
|
376
|
+
checkbox_name = name
|
377
|
+
end
|
378
|
+
|
379
|
+
# Copy all additional attributes and their values except the values array.
|
380
|
+
opts = args.clone
|
381
|
+
opts.delete(:values)
|
382
|
+
|
383
|
+
# Get the value and text to display for each checkbox
|
384
|
+
if value.class == Array
|
385
|
+
checkbox_text = value[0]
|
386
|
+
checkbox_value = value[1]
|
387
|
+
else
|
388
|
+
checkbox_text = checkbox_value = value
|
389
|
+
end
|
390
|
+
|
391
|
+
# Let's see if the current item is checked
|
392
|
+
if checkbox_value == checked
|
393
|
+
opts[:checked] = 'checked'
|
394
|
+
end
|
395
|
+
|
396
|
+
# And we're done, easy wasn't it?
|
397
|
+
opts = opts.merge(:name => checkbox_name, :id => id, :value => checkbox_value)
|
398
|
+
|
399
|
+
# Generate the following HTML:
|
400
|
+
#
|
401
|
+
# <span class="#{span_class}">
|
402
|
+
# <input type="checkbox" name="#{checkbox_name}" id="#{id}" value="#{value}" /> #{value}
|
403
|
+
# </span>
|
404
|
+
#
|
405
|
+
@g.span :class => span_class do
|
406
|
+
@g.input(opts)
|
407
|
+
" #{checkbox_text}"
|
408
|
+
end
|
409
|
+
end
|
410
|
+
end
|
105
411
|
end
|
106
412
|
end
|
107
413
|
alias checkbox input_checkbox
|
108
414
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
415
|
+
##
|
416
|
+
# Generate an input tag with a type of "radio". This method will also
|
417
|
+
# generate a hidden field with the same name as the radio button to ensure
|
418
|
+
# that the data is always submitted.
|
419
|
+
#
|
420
|
+
# If you want to generate multiple radio buttons you can use an array just like
|
421
|
+
# you can with checkboxes. Example:
|
422
|
+
#
|
423
|
+
# @data = Class.new
|
424
|
+
# attr_reader :gender_arr
|
425
|
+
# attr_reader :gender_hash
|
426
|
+
#
|
427
|
+
# def initialize
|
428
|
+
# @gender_arr = ['male', 'female']
|
429
|
+
# @gender_hash = {"Male" => "male", "Female" => "female"}
|
430
|
+
# end
|
431
|
+
# end.new
|
432
|
+
#
|
433
|
+
# form_for(@data, :method => :post) do |f|
|
434
|
+
# f.input_radio "Gender", :gender_arr
|
435
|
+
# f.input_radio "Gender", :gender_hash
|
436
|
+
# end
|
437
|
+
#
|
438
|
+
# @param [String] label The text to display inside the label tag.
|
439
|
+
# @param [String Symbol] name The name of the radio button.
|
440
|
+
# @param [String] checked String that indicates if (and which) radio button should be checked.
|
441
|
+
# @param [Hash] args Any additional HTML attributes along with their values.
|
442
|
+
# @see input_checkbox()
|
443
|
+
# @example
|
444
|
+
#
|
445
|
+
# form_for(@data, :method => :post) do |f|
|
446
|
+
# f.input_radio 'Gender', :gender
|
447
|
+
# end
|
448
|
+
#
|
449
|
+
def input_radio(label, name, checked = nil, args = {})
|
450
|
+
# Force a type of "radio"
|
451
|
+
args[:type] = :radio
|
452
|
+
|
453
|
+
if !args[:span_class]
|
454
|
+
args[:span_class] = "radio_wrap"
|
133
455
|
end
|
456
|
+
|
457
|
+
self.input_checkbox(label, name, checked, args)
|
134
458
|
end
|
135
459
|
alias radio input_radio
|
136
460
|
|
137
|
-
|
138
|
-
|
139
|
-
|
461
|
+
##
|
462
|
+
# Generate a field for uploading files.
|
463
|
+
#
|
464
|
+
# @param [String] label The text to display inside the label tag.
|
465
|
+
# @param [String Symbol] name The name of the radio tag.
|
466
|
+
# @param [Hash] args Any additional HTML attributes along with their values.
|
467
|
+
# @example
|
468
|
+
#
|
469
|
+
# form_for(@data, :method => :post) do |f|
|
470
|
+
# f.input_file 'Image', :image
|
471
|
+
# end
|
472
|
+
#
|
473
|
+
def input_file(label, name, args = {})
|
474
|
+
id = args[:id] ? args[:id] : id_for(name)
|
475
|
+
args = args.merge(:type => :file, :name => name, :id => id)
|
140
476
|
|
141
477
|
@g.p do
|
142
478
|
label_for(id, label, name)
|
@@ -145,17 +481,56 @@ module Ramaze
|
|
145
481
|
end
|
146
482
|
alias file input_file
|
147
483
|
|
148
|
-
|
149
|
-
|
150
|
-
|
484
|
+
##
|
485
|
+
# Generate a hidden field. Hidden fields are essentially the same as text fields
|
486
|
+
# except that they aren't displayed in the browser.
|
487
|
+
#
|
488
|
+
# @param [String Symbol] name The name of the hidden field tag.
|
489
|
+
# @param [String] value The value of the hidden field
|
490
|
+
# @param [Hash] args Any additional HTML attributes along with their values.
|
491
|
+
# @example
|
492
|
+
#
|
493
|
+
# form_for(@data, :method => :post) do |f|
|
494
|
+
# f.input_hidden :user_id
|
495
|
+
# end
|
496
|
+
#
|
497
|
+
def input_hidden(name, value = nil, args = {})
|
498
|
+
args = args.merge(:type => :hidden, :name => name)
|
499
|
+
|
500
|
+
if !value and @form_values.respond_to?(name)
|
501
|
+
args[:value] = @form_values.send(name)
|
502
|
+
else
|
503
|
+
args[:value] = value
|
504
|
+
end
|
151
505
|
|
152
506
|
@g.input(args)
|
153
507
|
end
|
154
508
|
alias hidden input_hidden
|
155
509
|
|
156
|
-
|
157
|
-
|
158
|
-
|
510
|
+
##
|
511
|
+
# Generate a text area.
|
512
|
+
#
|
513
|
+
# @param [String] label The text to display inside the label tag.
|
514
|
+
# @param [String Symbol] name The name of the textarea.
|
515
|
+
# @param [Hash] args Any additional HTML attributes along with their values.
|
516
|
+
# @example
|
517
|
+
#
|
518
|
+
# form_for(@data, :method => :post) do |f|
|
519
|
+
# f.textarea 'Description', :description
|
520
|
+
# end
|
521
|
+
#
|
522
|
+
def textarea(label, name, args = {})
|
523
|
+
id = args[:id] ? args[:id] : id_for(name)
|
524
|
+
|
525
|
+
# Get the value of the textarea
|
526
|
+
if !args[:value] and @form_values.respond_to?(name)
|
527
|
+
value = @form_values.send(name)
|
528
|
+
else
|
529
|
+
value = args[:value]
|
530
|
+
args.delete(:value)
|
531
|
+
end
|
532
|
+
|
533
|
+
args = args.merge(:name => name, :id => id)
|
159
534
|
|
160
535
|
@g.p do
|
161
536
|
label_for(id, label, name)
|
@@ -163,16 +538,39 @@ module Ramaze
|
|
163
538
|
end
|
164
539
|
end
|
165
540
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
541
|
+
##
|
542
|
+
# Generate a select tag along with the option tags and a label.
|
543
|
+
#
|
544
|
+
# @param [String] label The text to display inside the label tag.
|
545
|
+
# @param [String Symbol] name The name of the select tag.
|
546
|
+
# @param [Hash] args Hash containing additional HTML attributes.
|
547
|
+
# @example
|
548
|
+
#
|
549
|
+
# form_for(@data, :method => :post) do |f|
|
550
|
+
# f.select 'Country', :country_list
|
551
|
+
# end
|
552
|
+
#
|
553
|
+
def select(label, name, args = {})
|
554
|
+
id = args[:id] ? args[:id] : id_for(name)
|
555
|
+
multiple, size = args.values_at(:multiple, :size)
|
556
|
+
|
557
|
+
# Get all the values
|
558
|
+
if !args[:values] and @form_values.respond_to?(name)
|
559
|
+
values = @form_values.send(name)
|
560
|
+
else
|
561
|
+
values = args[:values]
|
562
|
+
args.delete(:values)
|
563
|
+
end
|
564
|
+
|
171
565
|
args[:multiple] = 'multiple' if multiple
|
172
|
-
args[:size]
|
173
|
-
args[:name]
|
566
|
+
args[:size] = (size || values.count || 1).to_i
|
567
|
+
args[:name] = multiple ? "#{name}[]" : name
|
568
|
+
args = args.merge(:id => id)
|
174
569
|
|
175
|
-
|
570
|
+
# Retrieve the selected value
|
571
|
+
has_selected, selected = args.key?(:selected), args[:selected]
|
572
|
+
selected = [selected] if !selected.is_a?(Array)
|
573
|
+
args.delete(:selected)
|
176
574
|
|
177
575
|
@g.p do
|
178
576
|
label_for(id, label, name)
|
@@ -180,19 +578,35 @@ module Ramaze
|
|
180
578
|
values.each do |value, o_name|
|
181
579
|
o_name ||= value
|
182
580
|
o_args = {:value => value}
|
183
|
-
|
581
|
+
|
582
|
+
if has_selected and selected.include?(value)
|
583
|
+
o_args[:selected] = 'selected'
|
584
|
+
end
|
585
|
+
|
184
586
|
@g.option(o_args){ o_name }
|
185
587
|
end
|
186
588
|
end
|
187
589
|
end
|
188
590
|
end
|
189
591
|
|
592
|
+
##
|
593
|
+
# Method used for converting the results of the BlueForm helper to a string
|
594
|
+
#
|
595
|
+
# @return [String] The form output
|
596
|
+
#
|
190
597
|
def to_s
|
191
598
|
@g.to_s
|
192
599
|
end
|
193
600
|
|
194
601
|
private
|
195
602
|
|
603
|
+
##
|
604
|
+
# Generate a label based on the id and value.
|
605
|
+
#
|
606
|
+
# @param [String] id The ID to which the label belongs.
|
607
|
+
# @param [String] value The text to display inside the label tag.
|
608
|
+
# @param [String] name The name of the field to which the label belongs.
|
609
|
+
#
|
196
610
|
def label_for(id, value, name)
|
197
611
|
if error = @form_errors.delete(name.to_s)
|
198
612
|
@g.label("#{value} ", :for => id){ @g.span(:class => :error){ error } }
|
@@ -201,11 +615,17 @@ module Ramaze
|
|
201
615
|
end
|
202
616
|
end
|
203
617
|
|
618
|
+
##
|
619
|
+
# Generate a value for an ID tag based on the field's name.
|
620
|
+
#
|
621
|
+
# @param [String] field_name The name of the field.
|
622
|
+
# @return [String] The ID for the specified field name.
|
623
|
+
#
|
204
624
|
def id_for(field_name)
|
205
625
|
if name = @form_args[:name]
|
206
|
-
"#{name}
|
626
|
+
"#{name}_#{field_name}".downcase.gsub(/-/, '_')
|
207
627
|
else
|
208
|
-
"
|
628
|
+
"form_#{field_name}".downcase.gsub(/-/, '_')
|
209
629
|
end
|
210
630
|
end
|
211
631
|
end
|