active_form 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.
Files changed (184) hide show
  1. data.tar.gz.sig +2 -0
  2. data/History.txt +4 -0
  3. data/License.txt +20 -0
  4. data/MIT-LICENSE +19 -0
  5. data/Manifest.txt +181 -0
  6. data/README.txt +1 -0
  7. data/Rakefile +4 -0
  8. data/config/hoe.rb +71 -0
  9. data/config/requirements.rb +17 -0
  10. data/init.rb +5 -0
  11. data/lib/active_form.rb +86 -0
  12. data/lib/active_form/core_extensions.rb +179 -0
  13. data/lib/active_form/definition.rb +72 -0
  14. data/lib/active_form/element.rb +50 -0
  15. data/lib/active_form/elements/base.rb +67 -0
  16. data/lib/active_form/elements/builder.rb +103 -0
  17. data/lib/active_form/elements/button.rb +15 -0
  18. data/lib/active_form/elements/checkbox.rb +18 -0
  19. data/lib/active_form/elements/file.rb +15 -0
  20. data/lib/active_form/elements/hidden.rb +9 -0
  21. data/lib/active_form/elements/image.rb +7 -0
  22. data/lib/active_form/elements/input.rb +23 -0
  23. data/lib/active_form/elements/password.rb +12 -0
  24. data/lib/active_form/elements/radio.rb +18 -0
  25. data/lib/active_form/elements/reset.rb +15 -0
  26. data/lib/active_form/elements/section.rb +37 -0
  27. data/lib/active_form/elements/select.rb +42 -0
  28. data/lib/active_form/elements/submit.rb +19 -0
  29. data/lib/active_form/elements/text.rb +9 -0
  30. data/lib/active_form/elements/textarea.rb +18 -0
  31. data/lib/active_form/errors.rb +73 -0
  32. data/lib/active_form/facets/checkbox_group.rb +11 -0
  33. data/lib/active_form/facets/collection_input.rb +96 -0
  34. data/lib/active_form/facets/radio_group.rb +11 -0
  35. data/lib/active_form/facets/select_date.rb +10 -0
  36. data/lib/active_form/facets/select_datetime.rb +10 -0
  37. data/lib/active_form/facets/select_day.rb +17 -0
  38. data/lib/active_form/facets/select_from_model.rb +60 -0
  39. data/lib/active_form/facets/select_hour.rb +17 -0
  40. data/lib/active_form/facets/select_minute.rb +17 -0
  41. data/lib/active_form/facets/select_month.rb +46 -0
  42. data/lib/active_form/facets/select_numeric_range.rb +59 -0
  43. data/lib/active_form/facets/select_second.rb +17 -0
  44. data/lib/active_form/facets/select_time.rb +10 -0
  45. data/lib/active_form/facets/select_timebased.rb +145 -0
  46. data/lib/active_form/facets/select_weekday.rb +46 -0
  47. data/lib/active_form/facets/select_year.rb +24 -0
  48. data/lib/active_form/mixins/attribute_methods.rb +33 -0
  49. data/lib/active_form/mixins/casting.rb +152 -0
  50. data/lib/active_form/mixins/collection_element_methods.rb +204 -0
  51. data/lib/active_form/mixins/common_methods.rb +350 -0
  52. data/lib/active_form/mixins/container_methods.rb +417 -0
  53. data/lib/active_form/mixins/css_methods.rb +70 -0
  54. data/lib/active_form/mixins/element_methods.rb +314 -0
  55. data/lib/active_form/mixins/javascript_methods.rb +99 -0
  56. data/lib/active_form/mixins/loader_methods.rb +72 -0
  57. data/lib/active_form/mixins/option_element_methods.rb +61 -0
  58. data/lib/active_form/mixins/validation_methods.rb +253 -0
  59. data/lib/active_form/validator.rb +47 -0
  60. data/lib/active_form/validators/alpha.rb +9 -0
  61. data/lib/active_form/validators/alphanum.rb +9 -0
  62. data/lib/active_form/validators/base.rb +132 -0
  63. data/lib/active_form/validators/digits.rb +9 -0
  64. data/lib/active_form/validators/email.rb +29 -0
  65. data/lib/active_form/validators/format.rb +15 -0
  66. data/lib/active_form/validators/length_range.rb +24 -0
  67. data/lib/active_form/validators/number.rb +9 -0
  68. data/lib/active_form/validators/option_count.rb +24 -0
  69. data/lib/active_form/validators/proc.rb +22 -0
  70. data/lib/active_form/validators/required.rb +9 -0
  71. data/lib/active_form/validators/set.rb +21 -0
  72. data/lib/active_form/validators/time_range.rb +30 -0
  73. data/lib/active_form/validators/uri.rb +54 -0
  74. data/lib/active_form/version.rb +9 -0
  75. data/lib/active_form/views/fieldsets.rb +34 -0
  76. data/lib/active_form/views/plain.rb +32 -0
  77. data/lib/active_form/views/tables.rb +28 -0
  78. data/lib/active_form/widget.rb +43 -0
  79. data/lib/active_form/widgets/base.rb +28 -0
  80. data/lib/loob/uri_validator.rb +140 -0
  81. data/lib/rails/acts_as_dropdown/MIT-LICENSE +20 -0
  82. data/lib/rails/acts_as_dropdown/acts_as_dropdown.rb +119 -0
  83. data/lib/rails/acts_as_dropdown/dropdown.rb +27 -0
  84. data/lib/rails/controller_helper.rb +19 -0
  85. data/lib/rails/model/loader.rb +206 -0
  86. data/lib/rails/view_helper.rb +20 -0
  87. data/samples/html/css/style.css +175 -0
  88. data/samples/html/js/effects.js +958 -0
  89. data/samples/html/js/prototype.js +2006 -0
  90. data/samples/html/js/validation.js +228 -0
  91. data/samples/html/plain_view.html +77 -0
  92. data/samples/html/sample001.html +158 -0
  93. data/samples/html/sample002.html +76 -0
  94. data/samples/html/sample003.html +34 -0
  95. data/samples/layouts/default.rhtml +18 -0
  96. data/samples/layouts/plain.rhtml +21 -0
  97. data/samples/layouts/sample003.rhtml +25 -0
  98. data/samples/plain_view.rb +58 -0
  99. data/samples/sample001.rb +111 -0
  100. data/samples/sample002.rb +92 -0
  101. data/samples/sample003.rb +30 -0
  102. data/script/destroy +14 -0
  103. data/script/generate +14 -0
  104. data/script/txt2html +74 -0
  105. data/setup.rb +1585 -0
  106. data/tasks/deployment.rake +34 -0
  107. data/tasks/environment.rake +7 -0
  108. data/tasks/website.rake +17 -0
  109. data/test/elements/test_base_element.rb +159 -0
  110. data/test/elements/test_builder_element.rb +81 -0
  111. data/test/elements/test_button_element.rb +12 -0
  112. data/test/elements/test_checkbox_element.rb +233 -0
  113. data/test/elements/test_file_element.rb +20 -0
  114. data/test/elements/test_hidden_element.rb +11 -0
  115. data/test/elements/test_image_element.rb +11 -0
  116. data/test/elements/test_input_element.rb +39 -0
  117. data/test/elements/test_password_element.rb +16 -0
  118. data/test/elements/test_radio_element.rb +197 -0
  119. data/test/elements/test_reset_element.rb +12 -0
  120. data/test/elements/test_section_element.rb +162 -0
  121. data/test/elements/test_select_element.rb +364 -0
  122. data/test/elements/test_submit_element.rb +12 -0
  123. data/test/elements/test_text_element.rb +91 -0
  124. data/test/elements/test_textarea_element.rb +23 -0
  125. data/test/facets/test_checkbox_group_element.rb +388 -0
  126. data/test/facets/test_radio_group_element.rb +312 -0
  127. data/test/facets/test_select_date_element.rb +211 -0
  128. data/test/facets/test_select_datetime_element.rb +56 -0
  129. data/test/facets/test_select_day_element.rb +37 -0
  130. data/test/facets/test_select_from_model_element.rb +86 -0
  131. data/test/facets/test_select_hour_element.rb +37 -0
  132. data/test/facets/test_select_minute_element.rb +52 -0
  133. data/test/facets/test_select_month_element.rb +79 -0
  134. data/test/facets/test_select_numeric_range_element.rb +14 -0
  135. data/test/facets/test_select_second_element.rb +48 -0
  136. data/test/facets/test_select_time_element.rb +148 -0
  137. data/test/facets/test_select_weekday_element.rb +71 -0
  138. data/test/facets/test_select_year_element.rb +73 -0
  139. data/test/fixtures/author.rb +11 -0
  140. data/test/fixtures/authors.yml +0 -0
  141. data/test/fixtures/book.rb +14 -0
  142. data/test/fixtures/books.yml +8 -0
  143. data/test/fixtures/categories.yml +0 -0
  144. data/test/fixtures/categorization.rb +2 -0
  145. data/test/fixtures/categorizations.yml +0 -0
  146. data/test/fixtures/category.rb +8 -0
  147. data/test/fixtures/publisher.rb +5 -0
  148. data/test/fixtures/publishers.yml +10 -0
  149. data/test/fixtures/schema.rb +43 -0
  150. data/test/rails/test_model_autodefinition.rb +121 -0
  151. data/test/rails/test_model_loader.rb +61 -0
  152. data/test/resources/elements/chunky.rb +11 -0
  153. data/test/resources/forms/demo.rb +5 -0
  154. data/test/resources/models/book.rb +8 -0
  155. data/test/resources/models/register_publisher.rb +5 -0
  156. data/test/resources/sections/demo.rb +6 -0
  157. data/test/resources/sections/foo.rb +6 -0
  158. data/test/resources/validators/foo.rb +9 -0
  159. data/test/resources/widgets/custom.rb +13 -0
  160. data/test/test_active_form.rb +1050 -0
  161. data/test/test_casting.rb +124 -0
  162. data/test/test_definition.rb +68 -0
  163. data/test/test_definition_class.rb +118 -0
  164. data/test/test_element_class.rb +201 -0
  165. data/test/test_helper.rb +74 -0
  166. data/test/test_javascript.rb +234 -0
  167. data/test/test_load_definition.rb +68 -0
  168. data/test/test_load_element.rb +35 -0
  169. data/test/test_load_section_element.rb +43 -0
  170. data/test/test_load_validator.rb +31 -0
  171. data/test/test_load_widget.rb +93 -0
  172. data/test/test_validation.rb +722 -0
  173. data/test/validators/test_validates_as_alpha.rb +26 -0
  174. data/test/validators/test_validates_as_alphanum.rb +26 -0
  175. data/test/validators/test_validates_as_digits.rb +26 -0
  176. data/test/validators/test_validates_as_email.rb +29 -0
  177. data/test/validators/test_validates_as_number.rb +26 -0
  178. data/test/validators/test_validates_as_uri.rb +128 -0
  179. data/test/validators/test_validates_with_format.rb +26 -0
  180. data/test/validators/test_validates_within_length_range.rb +46 -0
  181. data/test/validators/test_validates_within_set.rb +46 -0
  182. data/test/validators/test_validates_within_time_range.rb +53 -0
  183. metadata +307 -0
  184. metadata.gz.sig +4 -0
@@ -0,0 +1,9 @@
1
+ ActiveForm::Validator::Base.create :digits do
2
+
3
+ default_message "%s: should contain digits (0-9) only"
4
+
5
+ def validate
6
+ element.errors << advice[code] unless element.blank? || value.to_s =~ /^\d+$/
7
+ end
8
+
9
+ end
@@ -0,0 +1,29 @@
1
+ require 'resolv'
2
+
3
+ ActiveForm::Validator::Base.create :email do
4
+
5
+ REGEX = /^(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9]+@((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,6}$/
6
+
7
+ default_message "%s: is not a valid email address"
8
+
9
+ attr_accessor :resolve
10
+
11
+ def validate
12
+ email = value.to_s
13
+ element.errors << advice[code] unless email.blank? || (email =~ REGEX && (self.resolve ? resolve_address(email) : true))
14
+ end
15
+
16
+ private
17
+
18
+ def resolve_address(email)
19
+ hostname = email[(email =~ /@/)+1..email.length]
20
+ valid = true
21
+ begin
22
+ Resolv::DNS.new.getresource(hostname, Resolv::DNS::Resource::IN::MX)
23
+ rescue Resolv::ResolvError
24
+ valid = false
25
+ end
26
+ return valid
27
+ end
28
+
29
+ end
@@ -0,0 +1,15 @@
1
+ ActiveForm::Validator::Base.create :format do
2
+
3
+ default_message "%s: has an invalid format"
4
+
5
+ attr_accessor :regexp
6
+
7
+ def setup
8
+ self.regexp = /.*/
9
+ end
10
+
11
+ def validate
12
+ element.errors << advice[code] unless element.blank? || (self.regexp.kind_of?(Regexp) && value.to_s.match(self.regexp))
13
+ end
14
+
15
+ end
@@ -0,0 +1,24 @@
1
+ ActiveForm::Validator::Base.create :length_range do
2
+
3
+ # format position 3 contains the minimum value
4
+ # format position 4 contains the maximum value
5
+ # format position 5 contains the actual value length (server side only)
6
+ default_message "%1$s: length should be within %3$s and %4$s characters"
7
+
8
+ attr_accessor :range
9
+
10
+ def setup
11
+ self.range = (0..1)
12
+ end
13
+
14
+ def validate
15
+ length_range = self.range.respond_to?(:include?) ? self.range : []
16
+ element.errors << advice[code] unless length_range.include?(self.value_length)
17
+ end
18
+
19
+ def message_params
20
+ first = self.range.first rescue 0; last = self.range.last rescue 0
21
+ [first, last, self.value_length]
22
+ end
23
+
24
+ end
@@ -0,0 +1,9 @@
1
+ ActiveForm::Validator::Base.create :number do
2
+
3
+ default_message "%s: should be numeric"
4
+
5
+ def validate
6
+ element.errors << advice[code] unless element.blank? || value.to_s.match(/^[0-9\.,]+$/)
7
+ end
8
+
9
+ end
@@ -0,0 +1,24 @@
1
+ ActiveForm::Validator::Base.create :option_count do
2
+
3
+ # format position 3 contains the minimum value
4
+ # format position 4 contains the maximum value
5
+ # format position 5 contains the actual value length (server side only)
6
+ default_message "%1$s: you need to select %3$s items"
7
+
8
+ attr_accessor :range
9
+
10
+ def setup
11
+ self.range = (0..1)
12
+ end
13
+
14
+ def validate
15
+ length_range = self.range.respond_to?(:include?) ? self.range : []
16
+ element.errors << advice[code] unless length_range.include?(self.collection_length)
17
+ end
18
+
19
+ def message_params
20
+ first = self.range.first rescue 0; last = self.range.last rescue 0
21
+ [first, last, collection_length]
22
+ end
23
+
24
+ end
@@ -0,0 +1,22 @@
1
+ ActiveForm::Validator::Base.create :proc do
2
+
3
+ default_message '%s: validation failed'
4
+
5
+ def initialize(*args, &block)
6
+ @proc = block if block_given?
7
+ super(*args)
8
+ end
9
+
10
+ def proc=(proc)
11
+ @proc = proc
12
+ end
13
+
14
+ def validate
15
+ @proc.call(self)
16
+ end
17
+
18
+ def advice
19
+ Hash.new
20
+ end
21
+
22
+ end
@@ -0,0 +1,9 @@
1
+ ActiveForm::Validator::Base.create :required do
2
+
3
+ default_message "%s: can't be blank"
4
+
5
+ def validate
6
+ element.errors << advice[code] if element.blank?
7
+ end
8
+
9
+ end
@@ -0,0 +1,21 @@
1
+ ActiveForm::Validator::Base.create :set do
2
+
3
+ # format position 3 contains the allowed values
4
+ default_message "%1$s: invalid value"
5
+
6
+ attr_accessor :set
7
+
8
+ def setup
9
+ self.set = []
10
+ end
11
+
12
+ def validate
13
+ value_set = self.set.respond_to?(:include?) ? self.set : []
14
+ element.errors << advice[code] unless value_set.include?(self.value)
15
+ end
16
+
17
+ def message_params
18
+ [ [*self.set].join(', ') ]
19
+ end
20
+
21
+ end
@@ -0,0 +1,30 @@
1
+ ActiveForm::Validator::Base.create :time_range do
2
+
3
+ # format position 3 contains the minimum value
4
+ # format position 4 contains the maximum value
5
+ # format position 5 contains the actual value length (server side only)
6
+ default_message "%1$s: specify a valid time or date between %3$s and %4$s"
7
+
8
+ attr_accessor :range
9
+
10
+ def setup
11
+ self.range = (5.years.ago.beginning_of_year..6.years.from_now.beginning_of_year)
12
+ end
13
+
14
+ def validate
15
+ if self.range.respond_to?(:include?)
16
+ element_value = element.export_value_as(self.range.first.kind_of?(Time) ? :time : :date)
17
+ element.errors << advice[code] unless self.range.include?(element_value)
18
+ end
19
+ end
20
+
21
+ def message_params
22
+ first = self.range.first.to_s(:long) rescue Date.today.to_s(:long); last = self.range.last.to_s(:long) rescue Date.today.to_s(:long)
23
+ [first, last, self.value_length]
24
+ end
25
+
26
+ # TODO
27
+ def js_validation(validation_msg, code)
28
+ end
29
+
30
+ end
@@ -0,0 +1,54 @@
1
+ require 'loob/uri_validator'
2
+
3
+ ActiveForm::Validator::Base.create :uri do
4
+
5
+ attr_accessor :messages
6
+ # possible error statuses:
7
+ # :invalid_scheme
8
+ # :invalid_host
9
+ # :invalid_content_type
10
+ # :invalid_format
11
+ # :moved_permanently
12
+ # :not_accessible
13
+
14
+ # format position 3 contains the validation error status (server side only)
15
+ default_message "%s: is not a valid location"
16
+
17
+ attr_reader :uri_validator
18
+
19
+ delegate :response_codes, :content_types, :schemes, :hosts, :port, :to => :uri_validator
20
+ delegate :response_codes=, :content_types=, :schemes=, :hosts=, :port=, :to => :uri_validator
21
+
22
+ def initialize(*args, &block)
23
+ @uri_validator = Loob::UriValidator.new
24
+ setup # trigger setup after creation
25
+ props = args.last.is_a?(Hash) ? args.pop : {}
26
+ register_element(args.shift) if is_element?(args.first)
27
+ self.code = self.class.to_s.demodulize.underscore
28
+ props.each { |prop, value| send("#{prop}=", value) if respond_to?("#{prop}=") }
29
+ self.messages = {}
30
+ self.messages.default = self.message
31
+ yield self if block_given?
32
+ end
33
+
34
+ def validate
35
+ unless value.blank? || uri_validator.valid_uri?(value)
36
+ element.errors << advice[uri_validator.error.to_s]
37
+ end
38
+ end
39
+
40
+ def advice
41
+ list = {}
42
+ list.default = ActiveForm::Error.new(element, messages[:default], code, message_params)
43
+ list[code] = list.default
44
+ [:invalid_scheme, :invalid_host, :invalid_content_type, :invalid_format, :moved_permanently, :not_accessible].each do |mkey|
45
+ list[mkey.to_s] = ActiveForm::Error.new(element, messages[mkey], mkey.to_s, message_params) if messages.key?(mkey)
46
+ end
47
+ list
48
+ end
49
+
50
+ def message_params
51
+ [uri_validator.error.to_s.titleize || 'OK']
52
+ end
53
+
54
+ end
@@ -0,0 +1,9 @@
1
+ module ActiveForm #:nodoc:
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 0
5
+ TINY = 1
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
@@ -0,0 +1,34 @@
1
+ # TODO work in progress
2
+
3
+ ActiveForm::Definition.define_container_wrapper do |builder, elem, render|
4
+ builder.form(elem.element_attributes) {
5
+ builder.fieldset(:class => 'form') {
6
+ builder.legend(elem.label, :class => 'form')
7
+ elem.render_elements(builder)
8
+ }
9
+ builder << elem.script_tag
10
+ }
11
+ end
12
+
13
+ ActiveForm::Definition.define_element_wrapper do |builder, elem, render|
14
+ style = StyleAttribute.new
15
+ style << 'display: none' if elem.hidden?
16
+ builder.fieldset(:style => style) {
17
+ builder.legend { elem.render_label(builder) }
18
+ builder.div(:id => "sub-#{elem.identifier}", &render)
19
+ }
20
+ end
21
+
22
+ ActiveForm::Element::Base.define_element_wrapper do |builder, elem, render|
23
+ builder.div(:id => "elem_#{elem.identifier}", :class => elem.css, :style => elem.style) {
24
+ elem.render_label(builder)
25
+ render.call(builder)
26
+ }
27
+ end
28
+
29
+ ActiveForm::Element::Section.define_element_wrapper do |builder, elem, render|
30
+ builder.fieldset(:class => 'section') {
31
+ builder.legend(elem.label, :class => 'section')
32
+ builder.div(:id => "section-#{elem.identifier}", &render)
33
+ }
34
+ end
@@ -0,0 +1,32 @@
1
+ # TODO work in progress
2
+
3
+ ActiveForm::Definition.define_container_wrapper do |builder, elem, render|
4
+ builder.form(elem.element_attributes) {
5
+ builder.h3(elem.label)
6
+ elem.render_elements(builder)
7
+ builder << elem.script_tag
8
+ }
9
+ end
10
+
11
+ # ActiveForm::Definition.define_element_wrapper do |builder, elem, render|
12
+ # style = StyleAttribute.new
13
+ # style << 'display: none' if elem.hidden?
14
+ # builder.div(:style => style) {
15
+ # builder.h4 { elem.render_label(builder) }
16
+ # builder.div(:id => "sub-#{elem.identifier}", &render)
17
+ # }
18
+ # end
19
+
20
+ ActiveForm::Element::Base.define_element_wrapper do |builder, elem, render|
21
+ builder.div(:id => "elem_#{elem.identifier}", :class => elem.css, :style => elem.style) {
22
+ elem.render_label(builder)
23
+ render.call(builder)
24
+ }
25
+ end
26
+
27
+ ActiveForm::Element::Section.define_element_wrapper do |builder, elem, render|
28
+ builder.div(:class => 'section') {
29
+ builder.h4(elem.label, :id => "section-#{elem.identifier}-title")
30
+ builder.div(:id => "section-#{elem.identifier}", &render)
31
+ }
32
+ end
@@ -0,0 +1,28 @@
1
+ # TODO work in progress
2
+
3
+ ActiveForm::Definition.define_container_wrapper do |builder, elem, render|
4
+ builder.form(elem.element_attributes) {
5
+ builder.table {
6
+ builder.thead { builder.tr { builder.th(elem.label, :colspan => 2) } }
7
+ builder.tbody { elem.render_elements(builder) }
8
+ }
9
+ builder << elem.script_tag
10
+ }
11
+ end
12
+
13
+ ActiveForm::Definition.define_element_wrapper do |builder, elem, render|
14
+ style = StyleAttribute.new
15
+ style << 'display: none' if elem.hidden?
16
+ builder.tr { builder.td { builder.table(:style => style, &render) } }
17
+ end
18
+
19
+ ActiveForm::Element::Base.define_element_wrapper do |builder, elem, render|
20
+ builder.tr(:class => 'label') { builder.td(:colspan => 2) { elem.render_label(builder) } }
21
+ builder.tr(:id => "elem_#{elem.identifier}", :class => elem.css, :style => elem.style) { builder.td(:class => 'elem', :colspan => 2, &render) }
22
+ end
23
+
24
+ ActiveForm::Element::Section.define_element_wrapper do |builder, elem, render|
25
+ builder.tr(:class => 'header') { builder.td(:colspan => 2) { builder.h3(:onclick => "$('section-#{elem.identifier}').toggle()") { elem.render_label(builder) } } }
26
+ builder.tr(:class => 'advice') { builder.td(:colspan => 2) { builder << elem.validation_advice } }
27
+ builder.tr { builder.td { builder.div(:id => "section-#{elem.identifier}") { builder.table(:style => 'background: lightblue;', &render) } } }
28
+ end
@@ -0,0 +1,43 @@
1
+ module ActiveForm::Widget
2
+
3
+ include ActiveForm::Mixins::LoaderMethods
4
+
5
+ class << self
6
+
7
+ def element?(klass)
8
+ klass.respond_to?(:element?) && klass.element?
9
+ end
10
+
11
+ # loader related
12
+
13
+ def load_paths
14
+ @@load_paths ||= [*base_load_paths]
15
+ end
16
+
17
+ def base_load_paths
18
+ [ ::File.join(ActiveForm::BASE_PATH, 'widgets') ]
19
+ end
20
+
21
+ def instance(definition_name, klass, *args, &block)
22
+ args.unshift(definition_name) if args.empty? || args.first.kind_of?(Hash)
23
+ item = klass.new(*args)
24
+ item.instance_eval(&block) if block_given?
25
+ item
26
+ end
27
+
28
+ def create(definition_name, &block)
29
+ ActiveForm::Widget::Base::create(definition_name, &block)
30
+ end
31
+
32
+ def register(elem_class)
33
+ if element?(elem_class) && !self.methods.include?("#{elem_class.loadable_type}_element")
34
+ self.module_eval("
35
+ def #{elem_class.loadable_type}_widget(*args, &block)
36
+ define_widget(:#{elem_class.loadable_type}, *args, &block)
37
+ end")
38
+ end
39
+ end
40
+
41
+ end
42
+
43
+ end
@@ -0,0 +1,28 @@
1
+ class ActiveForm::Widget::Base < ActiveForm::Element::Section
2
+
3
+ def self.inherited(derivative)
4
+ ActiveForm::Widget::register(derivative) if derivative.kind_of?(ActiveForm::Widget::Base)
5
+ super
6
+ end
7
+
8
+ def self.create(definition_name, &block)
9
+ class_name = type_classname(definition_name)
10
+ if !ActiveForm::Widget.const_defined?(class_name)
11
+ ActiveForm::Widget.const_set(class_name, Class.new(self))
12
+ if klass = ActiveForm::Widget.const_get(class_name)
13
+ klass.setup_proc = (block_given? ? block : prc)
14
+ return klass
15
+ end
16
+ end
17
+ nil
18
+ end
19
+
20
+ def self.type_classname(type)
21
+ type.to_s.camelize
22
+ end
23
+
24
+ def self.element_type
25
+ "#{self.name.to_s.demodulize.underscore}_widget".to_sym
26
+ end
27
+
28
+ end