formidable 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +10 -0
- data/CHANGELOG +2 -0
- data/Gemfile +7 -0
- data/LICENSE +20 -0
- data/README.textile +78 -0
- data/TODO.txt +3 -0
- data/deps.rip +5 -0
- data/examples/basic.rb +41 -0
- data/examples/post.rb +65 -0
- data/examples/posts/config.ru +48 -0
- data/examples/posts/form.html.haml +19 -0
- data/examples/posts/models.rb +7 -0
- data/formidable.gemspec +38 -0
- data/formidable.pre.gemspec +8 -0
- data/lib/formidable.rb +9 -0
- data/lib/formidable/coercions.rb +50 -0
- data/lib/formidable/elements.rb +196 -0
- data/lib/formidable/renderers/nokogiri.rb +53 -0
- data/lib/formidable/renderers/string.rb +115 -0
- data/lib/formidable/rendering.rb +42 -0
- data/lib/formidable/validations.rb +94 -0
- data/lib/formidable/validations/class.rb +24 -0
- data/lib/formidable/validations/confirmation.rb +58 -0
- data/lib/formidable/validations/equality.rb +25 -0
- data/lib/formidable/validations/format.rb +23 -0
- data/lib/formidable/validations/length.rb +39 -0
- data/lib/formidable/validations/presence.rb +17 -0
- data/lib/formidable/version.rb +5 -0
- data/spec/formidable/coercions_spec.rb +106 -0
- data/spec/formidable/elements_spec.rb +21 -0
- data/spec/formidable/renderers/nokogiri_spec.rb +9 -0
- data/spec/formidable/renderers/string_spec.rb +9 -0
- data/spec/formidable/rendering_spec.rb +0 -0
- data/spec/formidable/validations/class_spec.rb +0 -0
- data/spec/formidable/validations/confirmation_spec.rb +0 -0
- data/spec/formidable/validations/equality_spec.rb +0 -0
- data/spec/formidable/validations/format_spec.rb +0 -0
- data/spec/formidable/validations/length_spec.rb +0 -0
- data/spec/formidable/validations/presence_spec.rb +0 -0
- data/spec/formidable/validations_spec.rb +9 -0
- data/spec/formidable_spec.rb +51 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +13 -0
- data/tasks.rb +38 -0
- data/vendor/cache/validatable-1.6.7.gem +0 -0
- metadata +107 -0
data/.gitignore
ADDED
data/CHANGELOG
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Jakub Stastny aka Botanicus & Pavel Kunc
|
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.textile
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
h1. About
|
2
|
+
|
3
|
+
Formidable takes care about your forms. You write a class and
|
4
|
+
|
5
|
+
* Get logic out of your views.
|
6
|
+
* Get logic out of your controllers (presenter pattern).
|
7
|
+
* Validations will work even if the form can't be mapped directly to the models.
|
8
|
+
* You can unit test your forms directly without touching the template layer at all.
|
9
|
+
|
10
|
+
* Validations
|
11
|
+
* Coercions
|
12
|
+
|
13
|
+
Forms contains quite complex logic which definitely shouldn't be in your views
|
14
|
+
|
15
|
+
h2. Defining Forms
|
16
|
+
|
17
|
+
h2. Saving Forms
|
18
|
+
|
19
|
+
h2. Validations
|
20
|
+
|
21
|
+
h2. Renderers
|
22
|
+
|
23
|
+
h2. Custom Fields
|
24
|
+
|
25
|
+
h2. Ideas
|
26
|
+
|
27
|
+
JS validation plugin
|
28
|
+
|
29
|
+
h1. Usage
|
30
|
+
|
31
|
+
h2. Form Definitions
|
32
|
+
|
33
|
+
<pre>
|
34
|
+
|
35
|
+
</pre>
|
36
|
+
|
37
|
+
h2. Controller Code
|
38
|
+
|
39
|
+
<pre>
|
40
|
+
class Posts
|
41
|
+
def new
|
42
|
+
@form ||= PostForm.new
|
43
|
+
@form.attributes[:method] = "POST"
|
44
|
+
end
|
45
|
+
|
46
|
+
def edit
|
47
|
+
@form ||= PostForm.new
|
48
|
+
@form.attributes[:method] = "PUT"
|
49
|
+
end
|
50
|
+
|
51
|
+
def create(raw_data)
|
52
|
+
@form = PostForm.new(nil, raw_data)
|
53
|
+
if @form.save
|
54
|
+
redirect url(:posts)
|
55
|
+
else
|
56
|
+
self.new
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def update(id, raw_data)
|
61
|
+
@form = PostForm.new(nil, raw_data)
|
62
|
+
if @form.update(id)
|
63
|
+
redirect url(:posts)
|
64
|
+
else
|
65
|
+
self.edit
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
</pre>
|
70
|
+
|
71
|
+
You can find more examples at the @examples@ directory.
|
72
|
+
|
73
|
+
h1. Links
|
74
|
+
|
75
|
+
* "Source Code":http://github.com/botanicus/formidable
|
76
|
+
* "Wiki":http://wiki.github.com/botanicus/formidable
|
77
|
+
* "API Docs":http://rdoc.info/projects/botanicus/formidable
|
78
|
+
* "Bug reporting":http://github.com/botanicus/formidable/issues
|
data/TODO.txt
ADDED
data/deps.rip
ADDED
data/examples/basic.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
|
4
|
+
|
5
|
+
require "formidable"
|
6
|
+
require "formidable/validations/presence"
|
7
|
+
|
8
|
+
class BasicForm < Formidable::Elements::Form
|
9
|
+
def setup(&block)
|
10
|
+
text_field(:name, id: "basic_form-name")
|
11
|
+
.validate_presence
|
12
|
+
.coerce { |value| value.to_i }
|
13
|
+
|
14
|
+
text_field(:rating, id: "basic_form-rating")
|
15
|
+
.validate_presence
|
16
|
+
.coerce(Integer)
|
17
|
+
|
18
|
+
fieldset(:i_brake_it) do
|
19
|
+
legend("yyyy", id: 'xxx')
|
20
|
+
text_field(:nono, id: "nono").validate_presence
|
21
|
+
end
|
22
|
+
|
23
|
+
group(:i_m_group) do
|
24
|
+
text_field(:groupa, id: 'xy')
|
25
|
+
end
|
26
|
+
block.call if block
|
27
|
+
submit("Save")
|
28
|
+
end
|
29
|
+
|
30
|
+
def save
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class MyForm < BasicForm
|
36
|
+
def setup
|
37
|
+
super do
|
38
|
+
text_field(:super_duper, id: 'super_duper')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/examples/post.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# text_field, text_area -> value = raw_data[key]
|
4
|
+
# raw_data == user: {}, tags: [{name: "Ruby"}]
|
5
|
+
# form = PostForm.new(@post.values, Author.all)
|
6
|
+
class PostForm < Formidable::Form
|
7
|
+
namespace :post
|
8
|
+
def initialize(raw_data, authors)
|
9
|
+
super(raw_data)
|
10
|
+
@authors = authors
|
11
|
+
end
|
12
|
+
|
13
|
+
text_field(:title)
|
14
|
+
.validate_presence.
|
15
|
+
text_field(:title) do
|
16
|
+
validate_presence
|
17
|
+
end
|
18
|
+
|
19
|
+
check_box(:published)
|
20
|
+
text_area
|
21
|
+
|
22
|
+
group(:tydenni_menu) do
|
23
|
+
check_box :svickova
|
24
|
+
check_box :knedlo_zelo
|
25
|
+
validate do
|
26
|
+
self.fields.inject(0) do |sum, check_box|
|
27
|
+
sum += 1 if check_box.selected?
|
28
|
+
sum
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
select(:author) do
|
34
|
+
@authors.each do |author|
|
35
|
+
option selected: (author == raw_data[:author])
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
submit(value: "Save")
|
40
|
+
button(type: "submit") { "Save" }
|
41
|
+
|
42
|
+
field(:password, id: "sdf") do
|
43
|
+
validate_length (0..10)
|
44
|
+
validate do
|
45
|
+
form.password_confirmation == value
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
field(:password_confirmation) do
|
50
|
+
validate { form.password == value }
|
51
|
+
end
|
52
|
+
|
53
|
+
fields_for(:author) do
|
54
|
+
field()
|
55
|
+
end
|
56
|
+
|
57
|
+
# <fieldset>
|
58
|
+
# <legend>User</legend>
|
59
|
+
# </fieldset>
|
60
|
+
fieldset("User") do
|
61
|
+
field(:name)
|
62
|
+
end
|
63
|
+
|
64
|
+
field(:tags, id: -> { |tag| "tag-#{tag.id}"}, array: true)
|
65
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
class Posts
|
4
|
+
def self.dispatcher(action)
|
5
|
+
Proc.new do |env|
|
6
|
+
self.new(env).send(action)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(env)
|
11
|
+
@env = env
|
12
|
+
end
|
13
|
+
|
14
|
+
def index
|
15
|
+
end
|
16
|
+
|
17
|
+
def new
|
18
|
+
@form ||= PostForm.new
|
19
|
+
@form.attributes[:method] = "POST"
|
20
|
+
end
|
21
|
+
|
22
|
+
def edit
|
23
|
+
@form ||= PostForm.new
|
24
|
+
@form.attributes[:method] = "PUT"
|
25
|
+
end
|
26
|
+
|
27
|
+
def create(raw_data)
|
28
|
+
@form = PostForm.new(nil, raw_data)
|
29
|
+
if @form.save
|
30
|
+
redirect url(:posts)
|
31
|
+
else
|
32
|
+
self.new
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def update(id, raw_data)
|
37
|
+
@form = PostForm.new(nil, raw_data)
|
38
|
+
if @form.update(id)
|
39
|
+
redirect url(:posts)
|
40
|
+
else
|
41
|
+
self.edit
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
map("/posts") do
|
47
|
+
Posts.dispatcher(:index)
|
48
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
/ You might not need to have a template for your form. In case you
|
2
|
+
/ don't have any special need, just use form.render and that's it.
|
3
|
+
|
4
|
+
/ Specify renderer you want to use.
|
5
|
+
= form.errors.render(ErrorsListRenderer.new)
|
6
|
+
|
7
|
+
/ Haml tags can take hash as an argument, so why not simply use form.attributes.
|
8
|
+
%form{form.attributes}
|
9
|
+
/ Render tags you want to display.
|
10
|
+
= form.post.title.render
|
11
|
+
/ Iterate over elements
|
12
|
+
- form.post.tags.each do |tag|
|
13
|
+
= tag.render
|
14
|
+
/ Or write fully customized HTML.
|
15
|
+
%label{for: "input-body"}
|
16
|
+
- if form.post.errors.on(:title)
|
17
|
+
%input#input-title.errors{name: "post[title]", value: form.post.title}
|
18
|
+
- else
|
19
|
+
%input#input-title{name: "post[title]", value: form.post.title}
|
data/formidable.gemspec
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/usr/bin/env gem build
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
# Run ./form.gemspec or gem build form.gemspec
|
5
|
+
# NOTE: we can't use require_relative because when we run gem build, it use eval for executing this file
|
6
|
+
require File.expand_path("../lib/formidable/version", __FILE__)
|
7
|
+
require "base64"
|
8
|
+
|
9
|
+
Gem::Specification.new do |s|
|
10
|
+
s.name = "formidable"
|
11
|
+
s.version = Formidable::VERSION
|
12
|
+
s.authors = ["Jakub Stastny aka Botanicus", "Pavel Kunc"]
|
13
|
+
s.homepage = "http://github.com/botanicus/formidable"
|
14
|
+
s.summary = "" # TODO: summary
|
15
|
+
s.description = "" # TODO: long description
|
16
|
+
s.cert_chain = nil
|
17
|
+
s.email = Base64.decode64("c3Rhc3RueUAxMDFpZGVhcy5jeg==\n")
|
18
|
+
s.has_rdoc = true
|
19
|
+
|
20
|
+
# files
|
21
|
+
s.files = `git ls-files`.split("\n")
|
22
|
+
|
23
|
+
s.require_paths = ["lib"]
|
24
|
+
|
25
|
+
# Ruby version
|
26
|
+
s.required_ruby_version = ::Gem::Requirement.new(">= 1.9")
|
27
|
+
|
28
|
+
begin
|
29
|
+
require "changelog"
|
30
|
+
rescue LoadError
|
31
|
+
warn "You have to have changelog gem installed for post install message"
|
32
|
+
else
|
33
|
+
s.post_install_message = CHANGELOG.new.version_changes
|
34
|
+
end
|
35
|
+
|
36
|
+
# RubyForge
|
37
|
+
s.rubyforge_project = "formidable"
|
38
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
#!/usr/bin/env gem build
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
# You might think this is a terrible mess and guess what, you're
|
5
|
+
# right mate! However say thanks to authors of RubyGems, not me.
|
6
|
+
eval(File.read("form.gemspec")).tap do |specification|
|
7
|
+
specification.version = "#{specification.version}.pre"
|
8
|
+
end
|
data/lib/formidable.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Formidable
|
4
|
+
module Coercions
|
5
|
+
MissingCoercion = Class.new(StandardError)
|
6
|
+
IncompatibleInterface = Class.new(StandardError)
|
7
|
+
|
8
|
+
def self.coercions
|
9
|
+
@coercions ||= Hash.new do |hash, key|
|
10
|
+
raise MissingCoercion, "No coercion defined for #{key}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# default coercions
|
15
|
+
coercions[:integer] = Proc.new { |value| value.to_i }
|
16
|
+
coercions[:float] = Proc.new { |value| value.to_f }
|
17
|
+
|
18
|
+
def self.included(klass)
|
19
|
+
if ! klass.method_defined?(:raw_data) || ! klass.method_defined?(:cleaned_data=)
|
20
|
+
raise IncompatibleInterface, "You are supposed to define #{klass}#raw_data and #{klass}#cleaned_data= in order to get coercions running!"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def cleaned_data
|
25
|
+
@cleaned_data ||= self.coerce!
|
26
|
+
end
|
27
|
+
|
28
|
+
def coercions
|
29
|
+
@coercions ||= Array.new
|
30
|
+
end
|
31
|
+
|
32
|
+
def coerce(type = nil, &block)
|
33
|
+
if type && block.nil?
|
34
|
+
coercions << Coercions.coercions[type]
|
35
|
+
elsif type.nil? && block
|
36
|
+
coercions << block
|
37
|
+
else
|
38
|
+
raise ArgumentError, "provide block or type"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def coerce!
|
43
|
+
self.cleaned_data = begin
|
44
|
+
coercions.inject(self.raw_data) do |coercion, raw_data|
|
45
|
+
coercion.call(raw_data)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,196 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "formidable/coercions"
|
4
|
+
require "formidable/rendering"
|
5
|
+
require "formidable/validations"
|
6
|
+
require "formidable/renderers/string"
|
7
|
+
|
8
|
+
module Formidable
|
9
|
+
module Elements
|
10
|
+
class Element
|
11
|
+
include Rendering
|
12
|
+
include Validations
|
13
|
+
include Coercions
|
14
|
+
|
15
|
+
attr_accessor :name, :raw_data, :content
|
16
|
+
attr_reader :attributes
|
17
|
+
|
18
|
+
def initialize(name, attributes = Hash.new, raw_data = nil)
|
19
|
+
@name, @attributes, @raw_data = name, attributes, raw_data
|
20
|
+
@attributes.merge!(name: name, value: raw_data)
|
21
|
+
end
|
22
|
+
|
23
|
+
def set_raw_data(raw_data)
|
24
|
+
@raw_data = self.attributes[:value] = raw_data
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class ElementList < Element # pro form, group, fieldset
|
29
|
+
# We had a few beers and we decided that this is pretty cool :)
|
30
|
+
# This will define DSL method for creating email_field
|
31
|
+
# @example Formidable::ElementList.register self, :email_field
|
32
|
+
def self.register(klass, method_name)
|
33
|
+
define_method(method_name) do |name, *args, &block|
|
34
|
+
element = klass.new(name, *args, &block)
|
35
|
+
elements << element
|
36
|
+
warn "Overriding method #{name}" if self.class.method_defined?(name)
|
37
|
+
self.class.send(:define_method, name) do
|
38
|
+
element
|
39
|
+
end
|
40
|
+
element
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
include GroupValidations
|
45
|
+
def initialize(*args, &block)
|
46
|
+
super(*args) # we need to get elements first
|
47
|
+
self.instance_eval(&block) if block
|
48
|
+
end
|
49
|
+
|
50
|
+
def elements
|
51
|
+
@elements ||= Array.new
|
52
|
+
end
|
53
|
+
|
54
|
+
def cleaned_data
|
55
|
+
self.elements.inject(Hash.new) do |result, element|
|
56
|
+
result[element.name] = element.cleaned_data
|
57
|
+
result
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def raw_data
|
62
|
+
self.elements.inject(Hash.new) do |result, element|
|
63
|
+
result[element.name] = element.raw_data
|
64
|
+
result
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
protected
|
69
|
+
def set_raw_data(raw_data)
|
70
|
+
self.elements.each do |element|
|
71
|
+
element.set_raw_data(raw_data[element.name]) if raw_data
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class Form < ElementList
|
77
|
+
renderer Renderers::Form
|
78
|
+
|
79
|
+
# TODO: prefix should be in the form definition (name or namespace)
|
80
|
+
def initialize(prefix = nil, attributes = Hash.new, raw_data = nil)
|
81
|
+
self.setup
|
82
|
+
super(prefix, attributes, raw_data)
|
83
|
+
set_raw_data(raw_data)
|
84
|
+
end
|
85
|
+
|
86
|
+
def setup
|
87
|
+
raise NotImplementedError, "You are supposed to redefine the setup method in subclasses of Element!"
|
88
|
+
end
|
89
|
+
|
90
|
+
def save(*args)
|
91
|
+
raise NotImplementedError, "You have to redefine this method in subclasses!"
|
92
|
+
end
|
93
|
+
alias_method :save!, :save
|
94
|
+
|
95
|
+
def update(*args)
|
96
|
+
raise NotImplementedError, "You have to redefine this method in subclasses!"
|
97
|
+
end
|
98
|
+
alias_method :update!, :update
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
class TextField < Element
|
103
|
+
ElementList.register(self, :text_field)
|
104
|
+
|
105
|
+
def initialize(name, attributes = Hash.new, raw_data = nil)
|
106
|
+
super(name, attributes.merge!(type: "text"), raw_data)
|
107
|
+
end
|
108
|
+
|
109
|
+
renderer Renderers::LabeledInputRenderer
|
110
|
+
end
|
111
|
+
|
112
|
+
class TextArea < Element
|
113
|
+
ElementList.register(self, :text_area)
|
114
|
+
|
115
|
+
renderer Renderers::LabeledInputRenderer
|
116
|
+
end
|
117
|
+
|
118
|
+
class HiddenField < Element
|
119
|
+
ElementList.register(self, :hidden_field)
|
120
|
+
|
121
|
+
renderer Renderers::LabeledInputRenderer
|
122
|
+
end
|
123
|
+
|
124
|
+
class Submit < Element
|
125
|
+
ElementList.register(self, :submit)
|
126
|
+
|
127
|
+
renderer Renderers::SimpleInputRenderer
|
128
|
+
|
129
|
+
def initialize(value = "Submit", attributes = Hash.new, raw_data = Hash.new)
|
130
|
+
super(:submit, attributes.merge(value: value, type: "submit"), raw_data)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
class Button < Element
|
135
|
+
ElementList.register(self, :button)
|
136
|
+
|
137
|
+
renderer Renderers::Button
|
138
|
+
end
|
139
|
+
|
140
|
+
class Group < ElementList
|
141
|
+
ElementList.register(self, :group)
|
142
|
+
|
143
|
+
renderer Renderers::Group
|
144
|
+
end
|
145
|
+
|
146
|
+
class Fieldset < ElementList
|
147
|
+
ElementList.register(self, :fieldset)
|
148
|
+
|
149
|
+
renderer Renderers::Fieldset
|
150
|
+
end
|
151
|
+
|
152
|
+
class Legend < Element
|
153
|
+
Fieldset.register(self, :legend)
|
154
|
+
|
155
|
+
renderer Renderers::SimpleTagRenderer
|
156
|
+
|
157
|
+
def initialize(content, attributes = Hash.new)
|
158
|
+
self.content = content
|
159
|
+
super(:legend, attributes)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
class FileField < Element
|
164
|
+
ElementList.register(self, :file_field)
|
165
|
+
|
166
|
+
renderer Renderers::LabeledInputRenderer
|
167
|
+
|
168
|
+
def initialize(*args)
|
169
|
+
super(*args)
|
170
|
+
self.form.multipart = true
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
class EmailField < TextField
|
175
|
+
ElementList.register(self, :email_field)
|
176
|
+
end
|
177
|
+
|
178
|
+
# zna to svoje name => vi kde v params to najit
|
179
|
+
# {date: "27-07-2010"} => {date: #<Date:x0>}
|
180
|
+
class DateSelectField < Element
|
181
|
+
# TOHLE BUDE V SUPERCLASS
|
182
|
+
# jak to ma dostat params?
|
183
|
+
def deserialize
|
184
|
+
# [:post, :title]
|
185
|
+
self.name.inject(params) do |hash, key|
|
186
|
+
hash[key]
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
# TOHLE BUDE TADY
|
191
|
+
def deserialize
|
192
|
+
Date.new(super)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|