formidable 0.0.1 → 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -8,3 +8,5 @@
8
8
 
9
9
  /*.gem
10
10
  .bundle
11
+
12
+ .rvmrc
@@ -14,17 +14,17 @@ Gem::Specification.new do |s|
14
14
  s.summary = "" # TODO: summary
15
15
  s.description = "" # TODO: long description
16
16
  s.cert_chain = nil
17
- s.email = Base64.decode64("c3Rhc3RueUAxMDFpZGVhcy5jeg==\n")
17
+ Base64.decode64("c3Rhc3RueUAxMDFpZGVhcy5jeg==\n")
18
18
  s.has_rdoc = true
19
-
19
+
20
20
  # files
21
21
  s.files = `git ls-files`.split("\n")
22
-
22
+
23
23
  s.require_paths = ["lib"]
24
-
24
+
25
25
  # Ruby version
26
26
  s.required_ruby_version = ::Gem::Requirement.new(">= 1.9")
27
-
27
+
28
28
  begin
29
29
  require "changelog"
30
30
  rescue LoadError
@@ -32,7 +32,7 @@ Gem::Specification.new do |s|
32
32
  else
33
33
  s.post_install_message = CHANGELOG.new.version_changes
34
34
  end
35
-
35
+
36
36
  # RubyForge
37
37
  s.rubyforge_project = "formidable"
38
38
  end
@@ -1,49 +1,65 @@
1
1
  # encoding: utf-8
2
2
 
3
- require "formidable/coercions"
4
3
  require "formidable/rendering"
5
- require "formidable/validations"
6
4
  require "formidable/renderers/string"
7
5
 
8
6
  module Formidable
9
7
  module Elements
10
- class Element
11
- include Rendering
12
- include Validations
13
- include Coercions
14
-
15
- attr_accessor :name, :raw_data, :content
8
+ class BasicElement
9
+ attr_accessor :tag, :name, :raw_data, :content
10
+ attr_writer :cleaned_data
16
11
  attr_reader :attributes
17
12
 
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)
13
+ include Rendering
14
+
15
+ def initialize(tag, name, attributes = Hash.new, raw_data = nil)
16
+ @tag, @name, @attributes = tag, name, attributes
17
+ @attributes.merge!(name: name) if name
18
+ self.raw_data = raw_data if raw_data
21
19
  end
22
-
23
- def set_raw_data(raw_data)
24
- @raw_data = self.attributes[:value] = raw_data
20
+
21
+ def cleaned_data
22
+ @cleaned_data || self.raw_data
25
23
  end
26
24
  end
27
25
 
28
- class ElementList < Element # pro form, group, fieldset
26
+ require "formidable/coercions"
27
+ require "formidable/validations"
28
+
29
+ class Element < BasicElement
30
+ include Validations
31
+ include Coercions
32
+ end
33
+
34
+ class ElementList < BasicElement # pro form, group, fieldset
29
35
  # We had a few beers and we decided that this is pretty cool :)
30
36
  # This will define DSL method for creating email_field
31
37
  # @example Formidable::ElementList.register self, :email_field
32
38
  def self.register(klass, method_name)
33
- define_method(method_name) do |name, *args, &block|
34
- element = klass.new(name, *args, &block)
39
+ define_method(method_name) do |*args, &block|
40
+ element = klass.new(*args, &block)
35
41
  elements << element
36
- warn "Overriding method #{name}" if self.class.method_defined?(name)
37
- self.class.send(:define_method, name) do
38
- element
42
+ unless element.name.nil?
43
+ if self.class.method_defined?(element.name)
44
+ warn "Overriding method #{element.name}"
45
+ end
46
+ self.class.send(:define_method, element.name) do
47
+ element
48
+ end
39
49
  end
40
50
  element
41
51
  end
42
52
  end
43
53
 
44
54
  include GroupValidations
45
- def initialize(*args, &block)
46
- super(*args) # we need to get elements first
55
+
56
+ # This is pretty much just a copy of Element#initialize, it's because
57
+ # if we'd use super, then the Element#raw_data=(raw_data) would be called,
58
+ # but we actually need to trigger the ElementList#raw_data=(raw_data).
59
+ def initialize(tag, name, attributes = Hash.new, raw_data = nil, &block)
60
+ @tag, @name, @attributes = tag, name, attributes
61
+ @attributes.merge!(name: name) if name
62
+ self.raw_data = raw_data if raw_data
47
63
  self.instance_eval(&block) if block
48
64
  end
49
65
 
@@ -51,24 +67,52 @@ module Formidable
51
67
  @elements ||= Array.new
52
68
  end
53
69
 
54
- def cleaned_data
70
+ def content
71
+ self.elements.inject(String.new) do |buffer, element|
72
+ buffer += "\n" + element.render
73
+ end
74
+ end
75
+
76
+ def raw_data
55
77
  self.elements.inject(Hash.new) do |result, element|
56
- result[element.name] = element.cleaned_data
78
+ if element.name && element.raw_data
79
+ result[element.name] = element.raw_data
80
+ end
57
81
  result
58
82
  end
59
83
  end
60
84
 
61
- def raw_data
85
+ def raw_data=(raw_data)
86
+ return if raw_data.nil?
87
+ raw_data.each do |key, value|
88
+ element = self.send(key)
89
+ element.raw_data = value
90
+ end
91
+ end
92
+
93
+ def cleaned_data
62
94
  self.elements.inject(Hash.new) do |result, element|
63
- result[element.name] = element.raw_data
95
+ if element.name && element.raw_data
96
+ result[element.name] = element.cleaned_data
97
+ end
64
98
  result
65
99
  end
66
100
  end
67
101
 
68
- protected
69
- def set_raw_data(raw_data)
102
+ # TODO: this should be done dynamically, something like:
103
+ # def name
104
+ # self.parent.name + @name
105
+ # end
106
+ def set_prefix(prefix)
70
107
  self.elements.each do |element|
71
- element.set_raw_data(raw_data[element.name]) if raw_data
108
+ if element.respond_to?(:elements) && element.name
109
+ element.set_prefix("#{prefix}[#{element.name}]")
110
+ end
111
+ if element.attributes[:name]
112
+ element.attributes[:name] = begin
113
+ "#{prefix}[#{element.attributes[:name]}]"
114
+ end
115
+ end
72
116
  end
73
117
  end
74
118
  end
@@ -77,10 +121,11 @@ module Formidable
77
121
  renderer Renderers::Form
78
122
 
79
123
  # TODO: prefix should be in the form definition (name or namespace)
80
- def initialize(prefix = nil, attributes = Hash.new, raw_data = nil)
124
+ def initialize(action, method = "POST", prefix = nil, attributes = Hash.new, raw_data = nil)
81
125
  self.setup
82
- super(prefix, attributes, raw_data)
83
- set_raw_data(raw_data)
126
+ super(:form, nil, attributes.merge!(action: action, method: method), raw_data)
127
+ set_prefix(prefix) if prefix
128
+ self.raw_data = raw_data
84
129
  end
85
130
 
86
131
  def setup
@@ -97,9 +142,18 @@ module Formidable
97
142
  end
98
143
  alias_method :update!, :update
99
144
  end
100
-
101
145
 
102
- class TextField < Element
146
+ class Input < Element
147
+ def initialize(name, attributes = Hash.new, raw_data = nil)
148
+ super(:input, name, attributes, raw_data)
149
+ end
150
+
151
+ def raw_data=(raw_data)
152
+ self.attributes[:value] = super(raw_data)
153
+ end
154
+ end
155
+
156
+ class TextField < Input
103
157
  ElementList.register(self, :text_field)
104
158
 
105
159
  def initialize(name, attributes = Hash.new, raw_data = nil)
@@ -112,29 +166,46 @@ module Formidable
112
166
  class TextArea < Element
113
167
  ElementList.register(self, :text_area)
114
168
 
115
- renderer Renderers::LabeledInputRenderer
169
+ renderer Renderers::SimpleTagRenderer
170
+
171
+ def initialize(*args, &block)
172
+ super(:textarea, *args, &block)
173
+ end
174
+
175
+ def raw_data=(raw_data)
176
+ @raw_data = self.content = raw_data
177
+ end
116
178
  end
117
179
 
118
- class HiddenField < Element
180
+ class HiddenField < Input
119
181
  ElementList.register(self, :hidden_field)
120
182
 
121
- renderer Renderers::LabeledInputRenderer
183
+ renderer Renderers::SimpleInputRenderer
184
+
185
+ def initialize(name, attributes = Hash.new, raw_data = nil)
186
+ super(name, attributes.merge!(type: "hidden"), raw_data)
187
+ end
122
188
  end
123
189
 
124
- class Submit < Element
190
+ class Submit < Input
125
191
  ElementList.register(self, :submit)
126
192
 
127
193
  renderer Renderers::SimpleInputRenderer
128
194
 
129
- def initialize(value = "Submit", attributes = Hash.new, raw_data = Hash.new)
130
- super(:submit, attributes.merge(value: value, type: "submit"), raw_data)
195
+ def initialize(value = "Submit", attributes = Hash.new)
196
+ super(nil, attributes.merge(value: value, type: "submit"))
131
197
  end
132
198
  end
133
199
 
134
200
  class Button < Element
135
201
  ElementList.register(self, :button)
136
202
 
137
- renderer Renderers::Button
203
+ renderer Renderers::SimpleTagRenderer
204
+
205
+ def initialize(attributes = Hash.new, &block)
206
+ self.content = block.call
207
+ super(:button, nil, attributes)
208
+ end
138
209
  end
139
210
 
140
211
  class Group < ElementList
@@ -159,20 +230,94 @@ module Formidable
159
230
  super(:legend, attributes)
160
231
  end
161
232
  end
162
-
163
- class FileField < Element
233
+
234
+ class FileField < Input
164
235
  ElementList.register(self, :file_field)
165
236
 
166
237
  renderer Renderers::LabeledInputRenderer
167
238
 
168
- def initialize(*args)
169
- super(*args)
239
+ def initialize(name, attributes = Hash.new)
240
+ super(name, attributes.merge!(type: "file"))
170
241
  self.form.multipart = true
171
242
  end
172
243
  end
173
244
 
174
- class EmailField < TextField
245
+ class EmailField < Input
175
246
  ElementList.register(self, :email_field)
247
+
248
+ renderer Renderers::LabeledInputRenderer
249
+
250
+ def initialize(name = :email, attributes = Hash.new, raw_data = nil)
251
+ super(name, attributes.merge!(type: "email"), raw_data)
252
+ end
253
+ end
254
+
255
+ class PasswordField < Input
256
+ ElementList.register(self, :password_field)
257
+
258
+ renderer Renderers::LabeledInputRenderer
259
+
260
+ def initialize(name = :password, attributes = Hash.new)
261
+ super(name, attributes.merge!(type: "password"))
262
+ end
263
+ end
264
+
265
+ class Select < ElementList
266
+ include Validations # for validations purposes it behaves just as an element # TODO: doesn't workf
267
+ # The reason is simple, Validations are already included in GroupValidations, so it doesn't really include the mixin here
268
+
269
+ ElementList.register(self, :select)
270
+
271
+ renderer Renderers::SimpleTagRenderer
272
+
273
+ def initialize(name, attributes = Hash.new, &block)
274
+ super(:select, name, attributes, &block)
275
+ end
276
+
277
+ def selected
278
+ self.elements.find do |element|
279
+ element.attributes[:selected]
280
+ end
281
+ end
282
+
283
+ def raw_data
284
+ self.selected.raw_data if self.selected
285
+ end
286
+
287
+ def raw_data=(raw_data)
288
+ if raw_data.nil?
289
+ self.selected.attributes.delete(:selected)
290
+ else
291
+ self.elements.find do |element|
292
+ if element.raw_data == raw_data
293
+ element.attributes[:selected] = true
294
+ end
295
+ end
296
+ end
297
+ end
298
+
299
+ def cleaned_data
300
+ self.selected && self.selected.cleaned_data
301
+ end
302
+ end
303
+
304
+ class Option < Element
305
+ Select.register(self, :option)
306
+
307
+ renderer Renderers::SimpleTagRenderer
308
+
309
+ def initialize(value, attributes = Hash.new, &block)
310
+ self.content = block.call
311
+ super(:option, nil, attributes.merge!(value: value))
312
+ end
313
+
314
+ def raw_data
315
+ @raw_data ||= self.attributes[:value]
316
+ end
317
+
318
+ def cleaned_data
319
+ @cleaned_data ||= self.raw_data
320
+ end
176
321
  end
177
322
 
178
323
  # zna to svoje name => vi kde v params to najit
@@ -10,7 +10,7 @@ module Formidable
10
10
  end
11
11
 
12
12
  def tag(name, attributes = nil, &block)
13
- "<#{name}#{hash_to_attributes_string(attributes) if attributes}>#{"\n#{block.call}\n" if block}</#{name}>"
13
+ "<#{name}#{hash_to_attributes_string(attributes) if attributes}>#{block.call if block}</#{name}>"
14
14
  end
15
15
 
16
16
  def self_close_tag(name, attributes = nil)
@@ -25,7 +25,9 @@ module Formidable
25
25
  def hash_to_attributes_string(hash)
26
26
  hash.inject("") do |buffer, pair|
27
27
  attribute, value = pair
28
- if value
28
+ if value == true
29
+ buffer += " #{attribute}"
30
+ elsif value
29
31
  buffer += " #{attribute}='#{value}'" # TODO: h(value)
30
32
  end
31
33
  buffer
@@ -41,25 +43,24 @@ module Formidable
41
43
 
42
44
  class SimpleTagRenderer < Renderer
43
45
  def render
44
- tag(element.name, element.attributes) { element.content } + "\n"
46
+ tag(element.tag, element.attributes) { element.content }
45
47
  end
46
48
  end
47
49
 
48
- class LabeledInputRenderer < SimpleInputRenderer
50
+ class LongTagRenderer < SimpleTagRenderer
49
51
  def render
50
- id = element.attributes[:id]
51
- raise "You have to provide id attribute if you want to use LabeledInputRenderer!" if id.nil?
52
- buffer = tag(:label, for: id) { element.attributes[:title] } + "\n"
53
- buffer + super
52
+ super + "\n"
54
53
  end
55
54
  end
56
55
 
57
- class Button < SimpleInputRenderer
56
+ class LabeledInputRenderer < SimpleInputRenderer
58
57
  def render
59
- tag(:button, element.attributes)
58
+ id = element.attributes[:id] || (element.attributes[:id] = "random-#{element.object_id}")
59
+ buffer = tag(:label, for: id) { element.attributes[:title] || element.attributes[:placeholder] } + "\n"
60
+ buffer + super
60
61
  end
61
62
  end
62
-
63
+
63
64
  class Fieldset < SimpleInputRenderer
64
65
  def render
65
66
  tag(:fieldset) do
@@ -83,20 +84,27 @@ module Formidable
83
84
  end.join("\n")
84
85
  end
85
86
  end
86
-
87
+
87
88
  class Form < Renderer
88
- def render
89
+ # = form.render
90
+ # = form.render do
91
+ # %div= form.submit
92
+ def render(&block)
89
93
  if method = element.attributes[:method]
90
94
  set_method(method)
91
95
  end
92
96
 
93
- tag(:form, element.attributes) do
94
- element.elements.map do |element|
95
- element.render
96
- end.join("\n")
97
+ block ||= begin
98
+ Proc.new do
99
+ element.elements.map do |element|
100
+ element.render
101
+ end.join("\n")
102
+ end
97
103
  end
104
+
105
+ tag(:form, element.attributes, &block)
98
106
  end
99
-
107
+
100
108
  protected
101
109
  def set_method(method)
102
110
  if method
@@ -17,19 +17,15 @@ module Formidable
17
17
  alias_method :add, :[]=
18
18
  end
19
19
 
20
- module Elements
21
- class Element
22
- def self.register_validation(klass, method_name) # TODO: pridavat to spis do validations mixinu nez primo do elementu
23
- define_method(method_name) do |*args, &block|
24
- validation = klass.new(self, *args, &block)
25
- validations << validation
26
- self
27
- end
20
+ module Validations
21
+ def self.register_validation(klass, method_name)
22
+ define_method(method_name) do |*args, &block|
23
+ validation = klass.new(self, *args, &block)
24
+ validations << validation
25
+ self
28
26
  end
29
27
  end
30
- end
31
28
 
32
- module Validations
33
29
  def errors
34
30
  @errors ||= Array.new
35
31
  end
@@ -39,10 +35,11 @@ module Formidable
39
35
  end
40
36
 
41
37
  def valid?
42
- @errors || self.validate
38
+ self.validate
43
39
  end
44
40
 
45
41
  def validate
42
+ self.errors.clear
46
43
  self.validations.inject(true) do |is_valid, validation|
47
44
  validation_passed = validation.valid?
48
45
  unless validation_passed
@@ -54,15 +51,31 @@ module Formidable
54
51
  end
55
52
 
56
53
  module GroupValidations # TODO: better name
57
- include Validations
54
+ def self.register_validation(klass, method_name)
55
+ define_method(method_name) do |*args, &block|
56
+ validation = klass.new(self, *args, &block)
57
+ validations << validation
58
+ self
59
+ end
60
+ end
61
+
58
62
  def errors
59
63
  @errors ||= Errors.new
60
64
  end
61
65
 
66
+ def validations
67
+ @validations ||= Array.new
68
+ end
69
+
70
+ def valid?
71
+ self.validate
72
+ end
73
+
62
74
  def before_validate
63
75
  end
64
76
 
65
77
  def validate
78
+ self.errors.clear
66
79
  self.before_validate
67
80
  self.elements.each do |element|
68
81
  unless element.valid?
@@ -75,7 +88,8 @@ module Formidable
75
88
 
76
89
  class Validations::Validation
77
90
  def self.register(method_name)
78
- Elements::Element.register_validation(self, method_name)
91
+ Validations.register_validation(self, method_name)
92
+ GroupValidations.register_validation(self, method_name)
79
93
  end
80
94
 
81
95
  attr_reader :element
@@ -12,7 +12,7 @@ module Formidable
12
12
  class ValidateConfirmation < Validation
13
13
  register(:validate_confirmation)
14
14
 
15
- def initialize(element, confirmation_field, &block)
15
+ def initialize(element, confirmation_field = nil, &block)
16
16
  set_confirmation_field(confirmation_field, block)
17
17
  super(element)
18
18
  end
@@ -22,13 +22,13 @@ module Formidable
22
22
  end
23
23
 
24
24
  def message
25
- "can't be empty"
25
+ "has to match #{@confirmation_field.name}"
26
26
  end
27
27
 
28
28
  protected
29
29
  def set_confirmation_field(field, callable)
30
30
  @confirmation_field = begin
31
- if field && callable.nil
31
+ if field && callable.nil?
32
32
  field
33
33
  elsif field.nil? && callable
34
34
  callable.call
@@ -41,18 +41,18 @@ module Formidable
41
41
  end
42
42
  end
43
43
 
44
- module Validatable
45
- class ValidatesConfirmationOf < ValidationBase #:nodoc:
46
- option :case_sensitive
47
- default :case_sensitive => true
48
-
49
- def valid?(instance)
50
- return instance.send(self.attribute) == instance.send("#{self.attribute}_confirmation".to_sym) if case_sensitive
51
- instance.send(self.attribute).to_s.casecmp(instance.send("#{self.attribute}_confirmation".to_sym).to_s) == 0
52
- end
53
-
54
- def message(instance)
55
- super || "doesn't match confirmation"
56
- end
57
- end
58
- end
44
+ # module Validatable
45
+ # class ValidatesConfirmationOf < ValidationBase #:nodoc:
46
+ # option :case_sensitive
47
+ # default :case_sensitive => true
48
+ #
49
+ # def valid?(instance)
50
+ # return instance.send(self.attribute) == instance.send("#{self.attribute}_confirmation".to_sym) if case_sensitive
51
+ # instance.send(self.attribute).to_s.casecmp(instance.send("#{self.attribute}_confirmation".to_sym).to_s) == 0
52
+ # end
53
+ #
54
+ # def message(instance)
55
+ # super || "doesn't match confirmation"
56
+ # end
57
+ # end
58
+ # end
@@ -5,6 +5,15 @@ module Formidable
5
5
  class ValidatePresence < Validation
6
6
  register(:validate_presence)
7
7
 
8
+ def initialize(*args)
9
+ super(*args)
10
+
11
+ # HTML 5
12
+ unless element.attributes.has_key?(:required)
13
+ element.attributes[:required] = true
14
+ end
15
+ end
16
+
8
17
  def valid?
9
18
  ! element.cleaned_data.nil?
10
19
  end
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Formidable
4
- VERSION = "0.0.1"
4
+ VERSION = "0.1"
5
5
  end
metadata CHANGED
@@ -4,9 +4,8 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 0
8
7
  - 1
9
- version: 0.0.1
8
+ version: "0.1"
10
9
  platform: ruby
11
10
  authors:
12
11
  - Jakub Stastny aka Botanicus
@@ -14,12 +13,12 @@ authors:
14
13
  autorequire:
15
14
  bindir: bin
16
15
  cert_chain:
17
- date: 2010-03-30 00:00:00 +01:00
16
+ date: 2010-11-03 00:00:00 +01:00
18
17
  default_executable:
19
18
  dependencies: []
20
19
 
21
20
  description: ""
22
- email: stastny@101ideas.cz
21
+ email:
23
22
  executables: []
24
23
 
25
24
  extensions: []
@@ -76,12 +75,13 @@ has_rdoc: true
76
75
  homepage: http://github.com/botanicus/formidable
77
76
  licenses: []
78
77
 
79
- post_install_message: "[\e[32mVersion 0.0.1\e[0m] Support for renderers\n"
78
+ post_install_message:
80
79
  rdoc_options: []
81
80
 
82
81
  require_paths:
83
82
  - lib
84
83
  required_ruby_version: !ruby/object:Gem::Requirement
84
+ none: false
85
85
  requirements:
86
86
  - - ">="
87
87
  - !ruby/object:Gem::Version
@@ -90,6 +90,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
90
90
  - 9
91
91
  version: "1.9"
92
92
  required_rubygems_version: !ruby/object:Gem::Requirement
93
+ none: false
93
94
  requirements:
94
95
  - - ">="
95
96
  - !ruby/object:Gem::Version
@@ -99,7 +100,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
99
100
  requirements: []
100
101
 
101
102
  rubyforge_project: formidable
102
- rubygems_version: 1.3.6
103
+ rubygems_version: 1.3.7
103
104
  signing_key:
104
105
  specification_version: 3
105
106
  summary: ""