formalize 0.0.1
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/lib/formalize/field.rb +159 -0
- data/lib/formalize/helpers.rb +35 -0
- data/lib/formalize/version.rb +3 -0
- data/lib/formalize.rb +59 -0
- metadata +50 -0
@@ -0,0 +1,159 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require "formalize/helpers"
|
3
|
+
|
4
|
+
class BasicField
|
5
|
+
include Helpers
|
6
|
+
|
7
|
+
def initialize(id, opts={})
|
8
|
+
@errors = []
|
9
|
+
@opts = opts
|
10
|
+
@opts[:name] = id
|
11
|
+
end
|
12
|
+
|
13
|
+
def input(attrs = @opts)
|
14
|
+
input = tag(:input, attrs)
|
15
|
+
attrs[:label] ? tag_content(:label, "#{ attrs[:label] } #{ input }") : input
|
16
|
+
end
|
17
|
+
|
18
|
+
def errors
|
19
|
+
# REVIEW: What gets returned when @errors is empty?
|
20
|
+
unless @errors.empty?
|
21
|
+
list_items = @errors.collect { |error| tag_content(:li, error)}.join("\n")
|
22
|
+
tag_content(:ul, list_items)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def errors=(message)
|
27
|
+
@errors.push(message)
|
28
|
+
end
|
29
|
+
|
30
|
+
def value
|
31
|
+
@opts[:value]
|
32
|
+
end
|
33
|
+
|
34
|
+
def value=(val)
|
35
|
+
@opts[:value] = val
|
36
|
+
end
|
37
|
+
|
38
|
+
def valid?
|
39
|
+
@errors.empty?
|
40
|
+
end
|
41
|
+
|
42
|
+
def validate
|
43
|
+
validate_presence if @opts.has_key?(:required)
|
44
|
+
validate_length if @opts.has_key?(:maxlength)
|
45
|
+
unless @opts[:value].nil? || @opts[:value].is_a?(Array) || @opts[:value].strip.empty?
|
46
|
+
validate_format if @opts.has_key?(:pattern)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def validate_presence
|
51
|
+
if @opts[:required] == true && @opts[:value].strip.empty?
|
52
|
+
@errors << "#{ @opts[:name].capitalize } must not be blank"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def validate_length
|
57
|
+
if @opts[:value].size > @opts[:maxlength].to_i
|
58
|
+
@errors << "#{ @opts[:name].capitalize } must not be more than #{ @opts[:maxlength] } characters long"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def validate_format
|
63
|
+
re = Regexp.new(@opts[:pattern])
|
64
|
+
unless re =~ @opts[:value]
|
65
|
+
@errors << "#{ @opts[:name].capitalize } must be in a valid format"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
class TextField < BasicField
|
72
|
+
def initialize(id, opts={})
|
73
|
+
super
|
74
|
+
@opts[:type] = :text
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
class EmailField < BasicField
|
79
|
+
def initialize(id, opts={})
|
80
|
+
super
|
81
|
+
@opts[:type] = :email
|
82
|
+
@opts[:pattern] ||= /^[^@]+@[^@]+\.[a-zA-Z]{2,6}$/
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class UrlField < BasicField
|
87
|
+
def initialize(id, opts={})
|
88
|
+
super
|
89
|
+
@opts[:type] = :url
|
90
|
+
# REVIEW: The HTML this renders isn't great. Maybe only apply this on post?
|
91
|
+
@opts[:pattern] ||= /^#{URI::regexp(['http', 'https'])}$/
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
class TextareaField < BasicField
|
96
|
+
def initialize(id, opts={})
|
97
|
+
super
|
98
|
+
@opts[:type] = :textarea
|
99
|
+
end
|
100
|
+
def input(attrs = @opts)
|
101
|
+
value = attrs.delete(:value)
|
102
|
+
input = tag_content(:textarea, value, attrs)
|
103
|
+
attrs[:label] ? tag_content(:label, "#{ attrs[:label] } #{ input }") : input
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
class RadioField < BasicField
|
108
|
+
attr_accessor :opts
|
109
|
+
def initialize(id, opts={})
|
110
|
+
super
|
111
|
+
@opts[:type] = :radio
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
class CheckboxField < BasicField
|
116
|
+
attr_accessor :opts
|
117
|
+
def initialize(id, opts={})
|
118
|
+
super
|
119
|
+
@opts[:type] = :checkbox
|
120
|
+
end
|
121
|
+
def input
|
122
|
+
attrs = @opts.dup
|
123
|
+
attrs[:name] = attrs[:name].to_s << '[]'
|
124
|
+
super(attrs)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
class Group < BasicField
|
129
|
+
def initialize(id, &block)
|
130
|
+
super
|
131
|
+
@choices = []
|
132
|
+
instance_eval(&block)
|
133
|
+
end
|
134
|
+
def input
|
135
|
+
@choices.collect { |choice| choice.input }.join("\n")
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
class RadioGroup < Group
|
140
|
+
def choice(value, choice_opts={})
|
141
|
+
choice_opts[:value] = value
|
142
|
+
@choices.push(RadioField.new(@opts[:name], choice_opts))
|
143
|
+
end
|
144
|
+
def value=(val)
|
145
|
+
@opts[:value] = val
|
146
|
+
@choices.each { |choice| choice.opts[:checked] = (choice.opts[:value] === val.to_sym) }
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
class CheckboxGroup < Group
|
151
|
+
def choice(value, choice_opts={})
|
152
|
+
choice_opts[:value] = value
|
153
|
+
@choices.push(CheckboxField.new(@opts[:name], choice_opts))
|
154
|
+
end
|
155
|
+
def value=(values)
|
156
|
+
@opts[:value] = values
|
157
|
+
@choices.each { |choice| choice.opts[:checked] = (values.include?(choice.opts[:value].to_s)) }
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Helpers
|
2
|
+
|
3
|
+
# TODO: This leaves a extra space when there are no attributes
|
4
|
+
def tag(name, opts = {})
|
5
|
+
attributes = tag_attributes(opts)
|
6
|
+
"<#{ name } #{ attributes }>"
|
7
|
+
end
|
8
|
+
|
9
|
+
# TODO: This leaves a extra space when there are no attributes
|
10
|
+
def tag_content(name, content, opts = {})
|
11
|
+
attributes = tag_attributes(opts)
|
12
|
+
"<#{ name } #{ attributes }>#{ content }</#{ name }>"
|
13
|
+
end
|
14
|
+
|
15
|
+
def tag_attributes(opts)
|
16
|
+
opts.sort.collect do |key, val|
|
17
|
+
next if key == :label # REVIEW: Move to a NonStandardAttributes constant?
|
18
|
+
case val
|
19
|
+
when TrueClass
|
20
|
+
"#{ key }"
|
21
|
+
when FalseClass
|
22
|
+
""
|
23
|
+
when Array
|
24
|
+
# REVIEW Comma or no comma? Not sure what attributes this could be used with
|
25
|
+
"#{ key }='#{ val.join(',') }'"
|
26
|
+
when Regexp
|
27
|
+
pattern = val.inspect[1..-2]
|
28
|
+
"#{ key }='#{ pattern }'"
|
29
|
+
else
|
30
|
+
"#{ key }='#{ val }'"
|
31
|
+
end
|
32
|
+
end.join(' ').squeeze(' ')
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
data/lib/formalize.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
require "formalize/version"
|
2
|
+
require "formalize/field"
|
3
|
+
|
4
|
+
module Form
|
5
|
+
|
6
|
+
def text(id, opts={})
|
7
|
+
@fields ||= {}
|
8
|
+
@fields[id] = TextField.new(id, opts)
|
9
|
+
end
|
10
|
+
|
11
|
+
def email(id, opts={})
|
12
|
+
@fields ||= {}
|
13
|
+
@fields[id] = EmailField.new(id, opts)
|
14
|
+
end
|
15
|
+
|
16
|
+
def url(id, opts={})
|
17
|
+
@fields ||= {}
|
18
|
+
@fields[id] = UrlField.new(id, opts)
|
19
|
+
end
|
20
|
+
|
21
|
+
def textarea(id, opts={})
|
22
|
+
@fields ||= {}
|
23
|
+
@fields[id] = TextareaField.new(id, opts)
|
24
|
+
end
|
25
|
+
|
26
|
+
def radio(id, &block)
|
27
|
+
@fields ||= {}
|
28
|
+
@fields[id] = RadioGroup.new(id, &block)
|
29
|
+
end
|
30
|
+
|
31
|
+
def checkbox(id, &block)
|
32
|
+
@fields ||= {}
|
33
|
+
@fields[id] = CheckboxGroup.new(id, &block)
|
34
|
+
end
|
35
|
+
|
36
|
+
def option(val, opts={})
|
37
|
+
end
|
38
|
+
|
39
|
+
def fill(params)
|
40
|
+
@fields.each do |id, field|
|
41
|
+
field.value = params[id.to_s] unless params[id.to_s].nil?
|
42
|
+
field.validate
|
43
|
+
end
|
44
|
+
self
|
45
|
+
end
|
46
|
+
|
47
|
+
def valid?
|
48
|
+
@fields.values.all? { |field| field.valid? }
|
49
|
+
end
|
50
|
+
|
51
|
+
def [](id)
|
52
|
+
@fields[id]
|
53
|
+
end
|
54
|
+
|
55
|
+
def to_s
|
56
|
+
@fields.values.collect { |field| "#{ field.errors }\n<p>#{ field.input }</p>\n" }.join.squeeze("\n").strip
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
metadata
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: formalize
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Alex Edwards
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-09-22 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: This is a very basic (and untested!) RubyGem to simplify web form creation,
|
15
|
+
validation and processing. It is designed for use with the Sinatra framework.
|
16
|
+
email:
|
17
|
+
- ajmedwards@gmail.com
|
18
|
+
executables: []
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- lib/formalize/field.rb
|
23
|
+
- lib/formalize/version.rb
|
24
|
+
- lib/formalize/helpers.rb
|
25
|
+
- lib/formalize.rb
|
26
|
+
homepage: ''
|
27
|
+
licenses: []
|
28
|
+
post_install_message:
|
29
|
+
rdoc_options: []
|
30
|
+
require_paths:
|
31
|
+
- lib
|
32
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
requirements: []
|
45
|
+
rubyforge_project:
|
46
|
+
rubygems_version: 1.8.11
|
47
|
+
signing_key:
|
48
|
+
specification_version: 3
|
49
|
+
summary: Form processing and validation for Sinatra.
|
50
|
+
test_files: []
|