formidable 0.0.1 → 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/.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: ""