padrino-helpers 0.1.0
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/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.rdoc +7 -0
- data/Rakefile +58 -0
- data/VERSION +1 -0
- data/lib/padrino-helpers.rb +16 -0
- data/lib/padrino-helpers/asset_tag_helpers.rb +97 -0
- data/lib/padrino-helpers/form_builder/abstract_form_builder.rb +139 -0
- data/lib/padrino-helpers/form_builder/standard_form_builder.rb +37 -0
- data/lib/padrino-helpers/form_helpers.rb +194 -0
- data/lib/padrino-helpers/format_helpers.rb +74 -0
- data/lib/padrino-helpers/output_helpers.rb +98 -0
- data/lib/padrino-helpers/render_helpers.rb +63 -0
- data/lib/padrino-helpers/tag_helpers.rb +42 -0
- data/test/active_support_helpers.rb +7 -0
- data/test/fixtures/markup_app/app.rb +61 -0
- data/test/fixtures/markup_app/views/capture_concat.erb +14 -0
- data/test/fixtures/markup_app/views/capture_concat.haml +13 -0
- data/test/fixtures/markup_app/views/content_for.erb +11 -0
- data/test/fixtures/markup_app/views/content_for.haml +9 -0
- data/test/fixtures/markup_app/views/content_tag.erb +11 -0
- data/test/fixtures/markup_app/views/content_tag.haml +9 -0
- data/test/fixtures/markup_app/views/fields_for.erb +8 -0
- data/test/fixtures/markup_app/views/fields_for.haml +6 -0
- data/test/fixtures/markup_app/views/form_for.erb +56 -0
- data/test/fixtures/markup_app/views/form_for.haml +47 -0
- data/test/fixtures/markup_app/views/form_tag.erb +57 -0
- data/test/fixtures/markup_app/views/form_tag.haml +45 -0
- data/test/fixtures/markup_app/views/link_to.erb +5 -0
- data/test/fixtures/markup_app/views/link_to.haml +4 -0
- data/test/fixtures/markup_app/views/mail_to.erb +3 -0
- data/test/fixtures/markup_app/views/mail_to.haml +3 -0
- data/test/fixtures/render_app/app.rb +53 -0
- data/test/fixtures/render_app/views/erb/test.erb +1 -0
- data/test/fixtures/render_app/views/haml/test.haml +1 -0
- data/test/fixtures/render_app/views/template/_user.haml +7 -0
- data/test/fixtures/render_app/views/template/haml_template.haml +1 -0
- data/test/fixtures/render_app/views/template/some_template.haml +2 -0
- data/test/helper.rb +73 -0
- data/test/test_asset_tag_helpers.rb +127 -0
- data/test/test_form_builder.rb +611 -0
- data/test/test_form_helpers.rb +406 -0
- data/test/test_format_helpers.rb +96 -0
- data/test/test_output_helpers.rb +63 -0
- data/test/test_render_helpers.rb +78 -0
- data/test/test_tag_helpers.rb +73 -0
- metadata +174 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Padrino
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "padrino-helpers"
|
8
|
+
gem.summary = "Helpers for padrino"
|
9
|
+
gem.description = "Tag helpers, asset helpers, form helpers, form builders and many more helpers for padrino"
|
10
|
+
gem.email = "nesquena@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/padrino/padrino-helpers"
|
12
|
+
gem.authors = ["Padrino Team", "Nathan Esquenazi", "Davide D'Agostino", "Arthur Chiu"]
|
13
|
+
gem.add_runtime_dependency "sinatra", ">= 0.9.2"
|
14
|
+
gem.add_development_dependency "haml", ">= 2.2.1"
|
15
|
+
gem.add_development_dependency "shoulda", ">= 0"
|
16
|
+
gem.add_development_dependency "mocha", ">= 0.9.7"
|
17
|
+
gem.add_development_dependency "rack-test", ">= 0.5.0"
|
18
|
+
gem.add_development_dependency "webrat", ">= 0.5.1"
|
19
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
20
|
+
end
|
21
|
+
Jeweler::GemcutterTasks.new
|
22
|
+
rescue LoadError
|
23
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
24
|
+
end
|
25
|
+
|
26
|
+
require 'rake/testtask'
|
27
|
+
Rake::TestTask.new(:test) do |test|
|
28
|
+
test.libs << 'lib' << 'test'
|
29
|
+
test.pattern = 'test/**/test_*.rb'
|
30
|
+
test.verbose = true
|
31
|
+
end
|
32
|
+
|
33
|
+
begin
|
34
|
+
require 'rcov/rcovtask'
|
35
|
+
Rcov::RcovTask.new do |test|
|
36
|
+
test.libs << 'test'
|
37
|
+
test.pattern = 'test/**/test_*.rb'
|
38
|
+
test.verbose = true
|
39
|
+
end
|
40
|
+
rescue LoadError
|
41
|
+
task :rcov do
|
42
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
task :test => :check_dependencies
|
47
|
+
|
48
|
+
task :default => :test
|
49
|
+
|
50
|
+
require 'rake/rdoctask'
|
51
|
+
Rake::RDocTask.new do |rdoc|
|
52
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
53
|
+
|
54
|
+
rdoc.rdoc_dir = 'rdoc'
|
55
|
+
rdoc.title = "padrino-helpers #{version}"
|
56
|
+
rdoc.rdoc_files.include('README*')
|
57
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
58
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../padrino-core/lib/padrino-core/support_lite'
|
2
|
+
Dir[File.dirname(__FILE__) + '/padrino-helpers/**/*.rb'].each {|file| require file }
|
3
|
+
|
4
|
+
module Padrino
|
5
|
+
module Helpers
|
6
|
+
def self.registered(app)
|
7
|
+
app.set :default_builder, 'StandardFormBuilder'
|
8
|
+
app.helpers Padrino::Helpers::OutputHelpers
|
9
|
+
app.helpers Padrino::Helpers::TagHelpers
|
10
|
+
app.helpers Padrino::Helpers::AssetTagHelpers
|
11
|
+
app.helpers Padrino::Helpers::FormHelpers
|
12
|
+
app.helpers Padrino::Helpers::FormatHelpers
|
13
|
+
app.helpers Padrino::Helpers::RenderHelpers
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module Padrino
|
2
|
+
module Helpers
|
3
|
+
module AssetTagHelpers
|
4
|
+
|
5
|
+
# Creates a div to display the flash of given type if it exists
|
6
|
+
# flash_tag(:notice, :class => 'flash', :id => 'flash-notice')
|
7
|
+
def flash_tag(kind, options={})
|
8
|
+
flash_text = flash[kind]
|
9
|
+
return '' if flash_text.blank?
|
10
|
+
options.reverse_merge!(:class => 'flash')
|
11
|
+
content_tag(:div, flash_text, options)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Creates a link element with given name, url and options
|
15
|
+
# link_to 'click me', '/dashboard', :class => 'linky'
|
16
|
+
# link_to('/dashboard', :class => 'blocky') do ... end
|
17
|
+
# parameters: name, url='javascript:void(0)', options={}, &block
|
18
|
+
def link_to(*args, &block)
|
19
|
+
if block_given?
|
20
|
+
url, options = (args[0] || 'javascript:void(0);'), (args[1] || {})
|
21
|
+
options.reverse_merge!(:href => url)
|
22
|
+
link_content = capture_html(&block)
|
23
|
+
result_link = content_tag(:a, link_content, options)
|
24
|
+
block_is_template?(block) ? concat_content(result_link) : result_link
|
25
|
+
else
|
26
|
+
name, url, options = args.first, (args[1] || 'javascript:void(0);'), (args[2] || {})
|
27
|
+
options.reverse_merge!(:href => url)
|
28
|
+
content_tag(:a, name, options)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Creates a mail link element with given name and caption
|
33
|
+
# mail_to "me@demo.com" => <a href="mailto:me@demo.com">me@demo.com</a>
|
34
|
+
# mail_to "me@demo.com", "My Email" => <a href="mailto:me@demo.com">My Email</a>
|
35
|
+
def mail_to(email, caption=nil, mail_options={})
|
36
|
+
html_options = mail_options.slice!(:cc, :bcc, :subject, :body)
|
37
|
+
mail_query = Rack::Utils.build_query(mail_options).gsub(/\+/, '%20').gsub('%40', '@')
|
38
|
+
mail_href = "mailto:#{email}"; mail_href << "?#{mail_query}" if mail_query.present?
|
39
|
+
link_to (caption || email), mail_href, html_options
|
40
|
+
end
|
41
|
+
|
42
|
+
# Creates an image element with given url and options
|
43
|
+
# image_tag('icons/avatar.png')
|
44
|
+
def image_tag(url, options={})
|
45
|
+
options.reverse_merge!(:src => image_path(url))
|
46
|
+
tag(:img, options)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Returns a stylesheet link tag for the sources specified as arguments
|
50
|
+
# stylesheet_link_tag 'style', 'application', 'layout'
|
51
|
+
def stylesheet_link_tag(*sources)
|
52
|
+
options = sources.extract_options!.symbolize_keys
|
53
|
+
sources.collect { |sheet| stylesheet_tag(sheet, options) }.join("\n")
|
54
|
+
end
|
55
|
+
|
56
|
+
# javascript_include_tag 'application', 'special'
|
57
|
+
def javascript_include_tag(*sources)
|
58
|
+
options = sources.extract_options!.symbolize_keys
|
59
|
+
sources.collect { |script| javascript_tag(script, options) }.join("\n")
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns the path to the image, either relative or absolute
|
63
|
+
def image_path(src)
|
64
|
+
src.gsub!(/\s/, '')
|
65
|
+
src =~ %r{^\s*(/|http)} ? src : File.join('/images', src)
|
66
|
+
end
|
67
|
+
|
68
|
+
protected
|
69
|
+
|
70
|
+
# stylesheet_tag('style', :media => 'screen')
|
71
|
+
def stylesheet_tag(source, options={})
|
72
|
+
options = options.dup.reverse_merge!(:href => stylesheet_path(source), :media => 'screen', :rel => 'stylesheet', :type => 'text/css')
|
73
|
+
tag(:link, options)
|
74
|
+
end
|
75
|
+
|
76
|
+
# javascript_tag 'application', :src => '/javascripts/base/application.js'
|
77
|
+
def javascript_tag(source, options={})
|
78
|
+
options = options.dup.reverse_merge!(:src => javascript_path(source), :type => 'text/javascript', :content => "")
|
79
|
+
tag(:script, options)
|
80
|
+
end
|
81
|
+
|
82
|
+
def javascript_path(source)
|
83
|
+
return source if source =~ /^http/
|
84
|
+
result_path = "/javascripts/#{File.basename(source, '.js')}.js"
|
85
|
+
stamp = File.exist?(result_path) ? File.mtime(result_path) : Time.now.to_i
|
86
|
+
"#{result_path}?#{stamp}"
|
87
|
+
end
|
88
|
+
|
89
|
+
def stylesheet_path(source)
|
90
|
+
return source if source =~ /^http/
|
91
|
+
result_path = "/stylesheets/#{File.basename(source, '.css')}.css"
|
92
|
+
stamp = File.exist?(result_path) ? File.mtime(result_path) : Time.now.to_i
|
93
|
+
"#{result_path}?#{stamp}"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
module Padrino
|
2
|
+
module Helpers
|
3
|
+
module FormBuilder
|
4
|
+
class AbstractFormBuilder
|
5
|
+
attr_accessor :template, :object
|
6
|
+
|
7
|
+
def initialize(template, object)
|
8
|
+
@template = template
|
9
|
+
@object = build_object(object)
|
10
|
+
raise "FormBuilder template must be initialized!" unless template
|
11
|
+
raise "FormBuilder object must be not be nil value. If there's no object, use a symbol instead! (i.e :user)" unless object
|
12
|
+
end
|
13
|
+
|
14
|
+
# f.error_messages
|
15
|
+
def error_messages(options={})
|
16
|
+
@template.error_messages_for(@object, options)
|
17
|
+
end
|
18
|
+
|
19
|
+
# f.label :username, :caption => "Nickname"
|
20
|
+
def label(field, options={})
|
21
|
+
options.reverse_merge!(:caption => field.to_s.titleize)
|
22
|
+
@template.label_tag(field_id(field), options)
|
23
|
+
end
|
24
|
+
|
25
|
+
# f.hidden_field :session_id, :value => "45"
|
26
|
+
def hidden_field(field, options={})
|
27
|
+
options.reverse_merge!(:value => field_value(field), :id => field_id(field))
|
28
|
+
@template.hidden_field_tag field_name(field), options
|
29
|
+
end
|
30
|
+
|
31
|
+
# f.text_field :username, :value => "(blank)", :id => 'username'
|
32
|
+
def text_field(field, options={})
|
33
|
+
options.reverse_merge!(:value => field_value(field), :id => field_id(field))
|
34
|
+
@template.text_field_tag field_name(field), options
|
35
|
+
end
|
36
|
+
|
37
|
+
# f.text_area :summary, :value => "(enter summary)", :id => 'summary'
|
38
|
+
def text_area(field, options={})
|
39
|
+
options.reverse_merge!(:value => field_value(field), :id => field_id(field))
|
40
|
+
@template.text_area_tag field_name(field), options
|
41
|
+
end
|
42
|
+
|
43
|
+
# f.password_field :password, :id => 'password'
|
44
|
+
def password_field(field, options={})
|
45
|
+
options.reverse_merge!(:value => field_value(field), :id => field_id(field))
|
46
|
+
@template.password_field_tag field_name(field), options
|
47
|
+
end
|
48
|
+
|
49
|
+
# f.select :color, :options => ['red', 'green'], :include_blank => true
|
50
|
+
# f.select :color, :collection => @colors, :fields => [:name, :id]
|
51
|
+
def select(field, options={})
|
52
|
+
options.reverse_merge!(:id => field_id(field), :selected => field_value(field))
|
53
|
+
@template.select_tag field_name(field), options
|
54
|
+
end
|
55
|
+
|
56
|
+
# f.check_box :remember_me, :value => 'true', :uncheck_value => '0'
|
57
|
+
def check_box(field, options={})
|
58
|
+
unchecked_value = options.delete(:uncheck_value) || '0'
|
59
|
+
options.reverse_merge!(:id => field_id(field), :value => '1')
|
60
|
+
options.merge!(:checked => true) if values_matches_field?(field, options[:value])
|
61
|
+
html = @template.check_box_tag field_name(field), options
|
62
|
+
html << hidden_field(field, :value => unchecked_value, :id => nil)
|
63
|
+
end
|
64
|
+
|
65
|
+
# f.radio_button :gender, :value => 'male'
|
66
|
+
def radio_button(field, options={})
|
67
|
+
options.reverse_merge!(:id => field_id(field, options[:value]))
|
68
|
+
options.merge!(:checked => true) if values_matches_field?(field, options[:value])
|
69
|
+
@template.radio_button_tag field_name(field), options
|
70
|
+
end
|
71
|
+
|
72
|
+
# f.file_field :photo, :class => 'avatar'
|
73
|
+
def file_field(field, options={})
|
74
|
+
options.reverse_merge!(:id => field_id(field))
|
75
|
+
@template.file_field_tag field_name(field), options
|
76
|
+
end
|
77
|
+
|
78
|
+
# f.submit "Update", :class => 'large'
|
79
|
+
def submit(caption="Submit", options={})
|
80
|
+
@template.submit_tag caption, options
|
81
|
+
end
|
82
|
+
|
83
|
+
# f.simage_submitubmit "buttons/submit.png", :class => 'large'
|
84
|
+
def image_submit(source, options={})
|
85
|
+
@template.image_submit_tag source, options
|
86
|
+
end
|
87
|
+
|
88
|
+
protected
|
89
|
+
|
90
|
+
# Returns the known field types for a formbuilder
|
91
|
+
def self.field_types
|
92
|
+
[:hidden_field, :text_field, :text_area, :password_field, :file_field, :radio_button, :check_box, :select]
|
93
|
+
end
|
94
|
+
|
95
|
+
# Returns the object's models name
|
96
|
+
# => user_assignment
|
97
|
+
def object_name
|
98
|
+
object.is_a?(Symbol) ? object : object.class.to_s.underscore
|
99
|
+
end
|
100
|
+
|
101
|
+
# Returns true if the value matches the value in the field
|
102
|
+
# field_has_value?(:gender, 'male')
|
103
|
+
def values_matches_field?(field, value)
|
104
|
+
value.present? && (field_value(field).to_s == value.to_s || field_value(field).to_s == 'true')
|
105
|
+
end
|
106
|
+
|
107
|
+
# Returns the value for the object's field
|
108
|
+
# field_value(:username) => "Joey"
|
109
|
+
def field_value(field)
|
110
|
+
@object && @object.respond_to?(field) ? @object.send(field) : ""
|
111
|
+
end
|
112
|
+
|
113
|
+
# Returns the name for the given field
|
114
|
+
# field_name(:username) => "user[username]"
|
115
|
+
def field_name(field)
|
116
|
+
"#{object_name}[#{field}]"
|
117
|
+
end
|
118
|
+
|
119
|
+
# Returns the id for the given field
|
120
|
+
# field_id(:username) => "user_username"
|
121
|
+
# field_id(:gender, :male) => "user_gender_male"
|
122
|
+
def field_id(field, value=nil)
|
123
|
+
value.blank? ? "#{object_name}_#{field}" : "#{object_name}_#{field}_#{value}"
|
124
|
+
end
|
125
|
+
|
126
|
+
# explicit_object is either a symbol or a record
|
127
|
+
# Returns a new record of the type specified in the object
|
128
|
+
def build_object(object_or_symbol)
|
129
|
+
object_or_symbol.is_a?(Symbol) ? object_class(object_or_symbol).new : object_or_symbol
|
130
|
+
end
|
131
|
+
|
132
|
+
# Returns the class type for the given object
|
133
|
+
def object_class(explicit_object)
|
134
|
+
explicit_object.is_a?(Symbol) ? explicit_object.to_s.classify.constantize : explicit_object.class
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Padrino
|
2
|
+
module Helpers
|
3
|
+
module FormBuilder
|
4
|
+
class StandardFormBuilder < AbstractFormBuilder
|
5
|
+
|
6
|
+
# text_field_block(:username, { :class => 'long' }, { :class => 'wide-label' })
|
7
|
+
# text_area_block(:summary, { :class => 'long' }, { :class => 'wide-label' })
|
8
|
+
# password_field_block(:password, { :class => 'long' }, { :class => 'wide-label' })
|
9
|
+
# file_field_block(:photo, { :class => 'long' }, { :class => 'wide-label' })
|
10
|
+
# check_box_block(:remember_me, { :class => 'long' }, { :class => 'wide-label' })
|
11
|
+
# select_block(:color, :options => ['green', 'black'])
|
12
|
+
(self.field_types - [ :hidden_field, :radio_button ]).each do |field_type|
|
13
|
+
class_eval <<-EOF
|
14
|
+
def #{field_type}_block(field, options={}, label_options={})
|
15
|
+
label_options.reverse_merge!(:caption => options.delete(:caption)) if options[:caption]
|
16
|
+
field_html = label(field, label_options)
|
17
|
+
field_html << #{field_type}(field, options)
|
18
|
+
@template.content_tag(:p, field_html)
|
19
|
+
end
|
20
|
+
EOF
|
21
|
+
end
|
22
|
+
|
23
|
+
# submit_block("Update")
|
24
|
+
def submit_block(caption, options={})
|
25
|
+
submit_html = self.submit(caption, options)
|
26
|
+
@template.content_tag(:p, submit_html)
|
27
|
+
end
|
28
|
+
|
29
|
+
# image_submit_block("submit.png")
|
30
|
+
def image_submit_block(source, options={})
|
31
|
+
submit_html = self.image_submit(source, options)
|
32
|
+
@template.content_tag(:p, submit_html)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,194 @@
|
|
1
|
+
module Padrino
|
2
|
+
module Helpers
|
3
|
+
module FormHelpers
|
4
|
+
# Constructs a form for object using given or default form_builder
|
5
|
+
# form_for :user, '/register' do |f| ... end
|
6
|
+
# form_for @user, '/register', :id => 'register' do |f| ... end
|
7
|
+
def form_for(object, url, settings={}, &block)
|
8
|
+
builder_class = configured_form_builder_class(settings[:builder])
|
9
|
+
form_html = capture_html(builder_class.new(self, object), &block)
|
10
|
+
form_tag(url, settings) { form_html }
|
11
|
+
end
|
12
|
+
|
13
|
+
# Constructs form fields for an object using given or default form_builder
|
14
|
+
# Used within an existing form to allow alternate objects within one form
|
15
|
+
# fields_for @user.assignment do |assignment| ... end
|
16
|
+
# fields_for :assignment do |assigment| ... end
|
17
|
+
def fields_for(object, settings={}, &block)
|
18
|
+
builder_class = configured_form_builder_class(settings[:builder])
|
19
|
+
fields_html = capture_html(builder_class.new(self, object), &block)
|
20
|
+
concat_content fields_html
|
21
|
+
end
|
22
|
+
|
23
|
+
# Constructs a form without object based on options
|
24
|
+
# form_tag '/register' do ... end
|
25
|
+
def form_tag(url, options={}, &block)
|
26
|
+
options.reverse_merge!(:method => 'post', :action => url)
|
27
|
+
options[:enctype] = "multipart/form-data" if options.delete(:multipart)
|
28
|
+
inner_form_html = hidden_form_method_field(options[:method]) + capture_html(&block)
|
29
|
+
concat_content content_tag('form', inner_form_html, options)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Constructs a field_set to group fields with given options
|
33
|
+
# field_set_tag("Office", :class => 'office-set')
|
34
|
+
# parameters: legend_text=nil, options={}
|
35
|
+
def field_set_tag(*args, &block)
|
36
|
+
options = args.extract_options!
|
37
|
+
legend_text = args[0].is_a?(String) ? args.first : nil
|
38
|
+
legend_html = legend_text.blank? ? '' : content_tag(:legend, legend_text)
|
39
|
+
field_set_content = legend_html + capture_html(&block)
|
40
|
+
concat_content content_tag('fieldset', field_set_content, options)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Constructs list html for the errors for a given object
|
44
|
+
# error_messages_for @user
|
45
|
+
def error_messages_for(record, options={})
|
46
|
+
return "" if record.blank? or record.errors.none?
|
47
|
+
options.reverse_merge!(:header_message => "The #{record.class.to_s.downcase} could not be saved!")
|
48
|
+
error_messages = record.errors.full_messages
|
49
|
+
error_items = error_messages.collect { |er| content_tag(:li, er) }.join("\n")
|
50
|
+
error_html = content_tag(:p, options.delete(:header_message))
|
51
|
+
error_html << content_tag(:ul, error_items, :class => 'errors-list')
|
52
|
+
content_tag(:div, error_html, :class => 'field-errors')
|
53
|
+
end
|
54
|
+
|
55
|
+
# Constructs a label tag from the given options
|
56
|
+
# label_tag :username, :class => 'long-label'
|
57
|
+
# label_tag :username, :class => 'long-label' do ... end
|
58
|
+
def label_tag(name, options={}, &block)
|
59
|
+
options.reverse_merge!(:caption => name.to_s.titleize, :for => name)
|
60
|
+
caption_text = options.delete(:caption) + ": "
|
61
|
+
if block_given? # label with inner content
|
62
|
+
label_content = caption_text + capture_html(&block)
|
63
|
+
concat_content(content_tag(:label, label_content, options))
|
64
|
+
else # regular label
|
65
|
+
content_tag(:label, caption_text, options)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Constructs a hidden field input from the given options
|
70
|
+
# hidden_field_tag :session_key, :value => "__secret__"
|
71
|
+
def hidden_field_tag(name, options={})
|
72
|
+
options.reverse_merge!(:name => name)
|
73
|
+
input_tag(:hidden, options)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Constructs a text field input from the given options
|
77
|
+
# text_field_tag :username, :class => 'long'
|
78
|
+
def text_field_tag(name, options={})
|
79
|
+
options.reverse_merge!(:name => name)
|
80
|
+
input_tag(:text, options)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Constructs a text area input from the given options
|
84
|
+
# text_area_tag :username, :class => 'long'
|
85
|
+
def text_area_tag(name, options={})
|
86
|
+
options.reverse_merge!(:name => name)
|
87
|
+
content_tag(:textarea, '', options)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Constructs a password field input from the given options
|
91
|
+
# password_field_tag :password, :class => 'long'
|
92
|
+
def password_field_tag(name, options={})
|
93
|
+
options.reverse_merge!(:name => name)
|
94
|
+
input_tag(:password, options)
|
95
|
+
end
|
96
|
+
|
97
|
+
# Constructs a check_box from the given options
|
98
|
+
# options = [['caption', 'value'], ['Green', 'green1'], ['Blue', 'blue1'], ['Black', "black1"]]
|
99
|
+
# options = ['option', 'red', 'yellow' ]
|
100
|
+
# select_tag(:favorite_color, :options => ['red', 'yellow'], :selected => 'green1')
|
101
|
+
# select_tag(:country, :collection => @countries, :fields => [:name, :code])
|
102
|
+
def select_tag(name, options={})
|
103
|
+
options.reverse_merge!(:name => name)
|
104
|
+
collection, fields = options.delete(:collection), options.delete(:fields)
|
105
|
+
options[:options] = options_from_collection(collection, fields) if collection
|
106
|
+
options[:options].unshift('') if options.delete(:include_blank)
|
107
|
+
select_options_html = options_for_select(options.delete(:options), options.delete(:selected))
|
108
|
+
options.merge!(:name => "#{options[:name]}[]") if options[:multiple]
|
109
|
+
content_tag(:select, select_options_html, options)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Constructs a check_box from the given options
|
113
|
+
# check_box_tag :remember_me, :value => 'Yes'
|
114
|
+
def check_box_tag(name, options={})
|
115
|
+
options.reverse_merge!(:name => name, :value => '1')
|
116
|
+
input_tag(:checkbox, options)
|
117
|
+
end
|
118
|
+
|
119
|
+
# Constructs a radio_button from the given options
|
120
|
+
# radio_button_tag :remember_me, :value => 'true'
|
121
|
+
def radio_button_tag(name, options={})
|
122
|
+
options.reverse_merge!(:name => name)
|
123
|
+
input_tag(:radio, options)
|
124
|
+
end
|
125
|
+
|
126
|
+
# Constructs a file field input from the given options
|
127
|
+
# file_field_tag :photo, :class => 'long'
|
128
|
+
def file_field_tag(name, options={})
|
129
|
+
options.reverse_merge!(:name => name)
|
130
|
+
input_tag(:file, options)
|
131
|
+
end
|
132
|
+
|
133
|
+
# Constructs a submit button from the given options
|
134
|
+
# submit_tag "Create", :class => 'success'
|
135
|
+
def submit_tag(caption="Submit", options={})
|
136
|
+
options.reverse_merge!(:value => caption)
|
137
|
+
input_tag(:submit, options)
|
138
|
+
end
|
139
|
+
|
140
|
+
# Constructs a button input from the given options
|
141
|
+
# button_tag "Cancel", :class => 'clear'
|
142
|
+
def button_tag(caption, options = {})
|
143
|
+
options.reverse_merge!(:value => caption)
|
144
|
+
input_tag(:button, options)
|
145
|
+
end
|
146
|
+
|
147
|
+
# Constructs a submit button from the given options
|
148
|
+
# submit_tag "Create", :class => 'success'
|
149
|
+
def image_submit_tag(source, options={})
|
150
|
+
options.reverse_merge!(:src => image_path(source))
|
151
|
+
input_tag(:image, options)
|
152
|
+
end
|
153
|
+
|
154
|
+
protected
|
155
|
+
|
156
|
+
# Returns an array of option items for a select field based on the given collection
|
157
|
+
# fields is an array containing the fields to display from each item in the collection
|
158
|
+
def options_from_collection(collection, fields)
|
159
|
+
return '' if collection.blank?
|
160
|
+
collection.collect { |item| [ item.send(fields.first), item.send(fields.last) ] }
|
161
|
+
end
|
162
|
+
|
163
|
+
# Returns the options tags for a select based on the given option items
|
164
|
+
def options_for_select(option_items, selected_value=nil)
|
165
|
+
return '' if option_items.blank?
|
166
|
+
option_items.collect do |caption, value|
|
167
|
+
value ||= caption
|
168
|
+
content_tag(:option, caption, :value => value, :selected => selected_value.to_s =~ /#{value}|#{caption}/)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
# returns the hidden method field for 'put' and 'delete' forms
|
173
|
+
# Only 'get' and 'post' are allowed within browsers;
|
174
|
+
# 'put' and 'delete' are just specified using hidden fields with form action still 'put'.
|
175
|
+
# hidden_form_method_field('delete') => <input name="_method" value="delete" />
|
176
|
+
def hidden_form_method_field(desired_method)
|
177
|
+
return '' if (desired_method =~ /get|post/)
|
178
|
+
original_method = desired_method.dup
|
179
|
+
desired_method.replace('post')
|
180
|
+
hidden_field_tag(:_method, :value => original_method)
|
181
|
+
end
|
182
|
+
|
183
|
+
# Returns the FormBuilder class to use based on all available setting sources
|
184
|
+
# If explicitly defined, returns that, otherwise returns defaults
|
185
|
+
# configured_form_builder_class(nil) => StandardFormBuilder
|
186
|
+
def configured_form_builder_class(explicit_builder=nil)
|
187
|
+
default_builder = self.respond_to?(:options) && self.options.default_builder
|
188
|
+
configured_builder = explicit_builder || default_builder || 'StandardFormBuilder'
|
189
|
+
configured_builder = "Padrino::Helpers::FormBuilder::#{configured_builder}".constantize if configured_builder.is_a?(String)
|
190
|
+
configured_builder
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|