form_forms 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,28 @@
1
+ module FormForms
2
+ module Elements
3
+ class Block < BaseElement
4
+ allowed_sub_element :field
5
+ allowed_sub_element :block
6
+ allowed_sub_element :fieldset
7
+ allowed_sub_element :fields
8
+ allowed_sub_element :table_fields
9
+
10
+ def initialize(element, args = {})
11
+ @element = element.to_sym
12
+ self.args args
13
+ super
14
+ end
15
+
16
+ property :args
17
+
18
+ # Generate a fielset with a legend
19
+ def render(builder, view)
20
+ args = eval_property(:args, builder, view)
21
+
22
+ view.content_tag(@element, args) do
23
+ super
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,32 @@
1
+ module FormForms
2
+ module Elements
3
+ # This represents a single form field. Typically this is the most
4
+ # low-level part of a form. You can either return a form element with the
5
+ # help of the passed form builder or just return arbitrary html. The block
6
+ # is executed in the scope of the view where the form is rendered. You can
7
+ # use any helpers defined there.
8
+ #
9
+ # Note that you might need to mark your values as +html_safe+ to avoid
10
+ # superfluous escaping in the view.
11
+ #
12
+ # Example:
13
+ #
14
+ # my_form = Form.new() do |form|
15
+ # form.field(:subject) {|f| f.input :subject}
16
+ # form.field(:link) do |f|
17
+ # content_tag :p do
18
+ # content_tag(:a, :href => hint_path){ "This is a hint" }
19
+ # end
20
+ # end
21
+ # end
22
+ class Field
23
+ def initialize(&generator)
24
+ @generator = generator
25
+ end
26
+
27
+ def render(builder, view)
28
+ view.instance_exec(builder, &@generator)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,29 @@
1
+ module FormForms
2
+ module Elements
3
+ class Fields < BaseElement
4
+ allowed_sub_element :field
5
+ allowed_sub_element :block
6
+ allowed_sub_element :fieldset
7
+ allowed_sub_element :fields
8
+ allowed_sub_element :table_fields
9
+
10
+ def initialize(association=nil, form_args={})
11
+ self.association association
12
+ self.args form_args
13
+ super
14
+ end
15
+
16
+ property :association
17
+ property :args
18
+
19
+ def render(builder, view)
20
+ association = eval_property(:association, builder, view)
21
+ form_args = eval_property(:args, builder, view)
22
+
23
+ builder.association(association, form_args) do |sub|
24
+ render_elements(sub, view)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,23 @@
1
+ module FormForms
2
+ module Elements
3
+ class Fieldset < Block
4
+ def initialize(fieldset_args={}, &generator)
5
+ self.legend nil
6
+ super(:fieldset, fieldset_args, &generator)
7
+ end
8
+
9
+ property :legend
10
+
11
+ # Generate a fielset with a legend
12
+ def render(builder, view)
13
+ args = eval_property(:args, builder, view)
14
+ legend = eval_property(:legend, builder, view)
15
+
16
+ view.content_tag(:fieldset, args) do
17
+ view.concat view.content_tag(:legend, legend) unless legend.nil?
18
+ view.concat render_elements(builder, view)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,25 @@
1
+ module FormForms
2
+ class FormRegistry
3
+ class << self
4
+ def [](name)
5
+ forms[name.to_sym]
6
+ end
7
+
8
+ def []=(name, form)
9
+ forms[name.to_sym] = form
10
+ end
11
+
12
+ def delete(name)
13
+ forms.delete(name.to_sym)
14
+ end
15
+
16
+ def keys
17
+ forms.keys
18
+ end
19
+ protected
20
+ def forms
21
+ @forms ||= {}
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,2 @@
1
+ require 'form_forms/forms/base_form'
2
+ require 'form_forms/forms/form'
@@ -0,0 +1,40 @@
1
+ module FormForms
2
+ module Forms
3
+ # The generic top-level form for building a simple_form..
4
+ #
5
+ # This class (and all its children) is only usable as a top-level form
6
+ # as it generates its own form builder object which is passed to its
7
+ # sub-elements on rendering
8
+ class BaseForm < FormForms::Elements::BaseElement
9
+ # +form_args+ are passed to the initializer of the form builder.
10
+ # They can be used to override its defaults.
11
+ def initialize(form_args = {})
12
+ @form_args = form_args
13
+ super
14
+ end
15
+
16
+ # Set the form_args. These are static as we don't have a form yet
17
+ def args(form_args=nil)
18
+ if form_args
19
+ @form_args = form_args
20
+ else
21
+ @form_args
22
+ end
23
+ end
24
+
25
+ # Render the form.
26
+ # Notice that forms receive an ActiveModel object as its first
27
+ # parameter, unlike elements which receive the form builder which is
28
+ # created by a form.
29
+ def render(model, view)
30
+ view.simple_form_for(model, self.args) do |builder|
31
+ render_elements(builder, view)
32
+ end
33
+ end
34
+
35
+ def self.register(name, form_args={}, &generator)
36
+ ::FormForms::FormRegistry[name] = self.new(form_args, &generator)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,15 @@
1
+ module FormForms
2
+ module Forms
3
+ # The generic form for building a simple_form..
4
+ #
5
+ # This class is only usable as a top-level form as it generates its own
6
+ # form builder object
7
+ class Form < BaseForm
8
+ allowed_sub_element :field
9
+ allowed_sub_element :block
10
+ allowed_sub_element :fieldset
11
+ allowed_sub_element :fields
12
+ allowed_sub_element :table_fields
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,3 @@
1
+ module Formforms
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,32 @@
1
+ require 'test_helper'
2
+
3
+ class FieldsetTest < ActionView::TestCase
4
+ test "create a block" do
5
+ with_form_for(@user) do |form|
6
+ form.block(:red_box, :div, :class => "red_box") do |block|
7
+ block.field(:credit_card) {|f| f.input :credit_card}
8
+ end
9
+ end
10
+
11
+ assert_select 'form > div.red_box input.string#user_credit_card'
12
+ end
13
+
14
+ test "allow nesting of blocks" do
15
+ with_form_for(@user) do |form|
16
+ form.block(:main, :div, :id => 'main') do |outer|
17
+ outer.fieldset(:payment, :id => "payment") do |inner|
18
+ inner.legend "These are some fields"
19
+ inner.field(:credit_card) {|f| f.input :credit_card}
20
+ end
21
+
22
+ outer.field(:name) {|f| f.input :name}
23
+ end
24
+ end
25
+
26
+ assert_no_select 'fieldset#main > legend'
27
+ assert_select 'form > div#main > div > input.string#user_name'
28
+
29
+ assert_select 'form > div#main > fieldset#payment > legend', "These are some fields"
30
+ assert_select 'form > div#main > fieldset#payment input.string#user_credit_card'
31
+ end
32
+ end
@@ -0,0 +1,98 @@
1
+ require 'test_helper'
2
+
3
+ class FieldTest < ActionView::TestCase
4
+ test "render a simple_form field" do
5
+ with_form_for(@user) do |form|
6
+ form.field(:name) {|f| f.input :name}
7
+ form.field(:description) {|f| f.input :description}
8
+ end
9
+
10
+ assert_select 'input.string#user_name'
11
+ assert_select 'textarea.text#user_description'
12
+ end
13
+
14
+ test "render a custom field" do
15
+ with_form_for(@user) do |form|
16
+ form.field(:something) {|f| '<span id="foo">Something</span>'.html_safe}
17
+ end
18
+
19
+ assert_select 'span#foo', "Something"
20
+ end
21
+
22
+ test "escape unsafe output" do
23
+ with_form_for(@user) do |form|
24
+ form.field(:something) {|f| '<span id="foo">Something</span>'}
25
+ end
26
+
27
+ assert_no_select 'span#foo'
28
+ assert_select 'form', /&lt;span id=&quot;foo&quot;&gt;Something&lt;\/span&gt;/
29
+ end
30
+
31
+ test "allow the usage of view helpers" do
32
+ with_form_for(@user) do |form|
33
+ form.field(:something) {|f| content_tag(:span){"Something"}}
34
+ end
35
+
36
+ assert_select 'span', "Something"
37
+ end
38
+
39
+ test "allow appending elements" do
40
+ with_form_for(@user) do |form|
41
+ form.field(:name) {|f| f.input :name}
42
+ form.field(:description) {|f| f.input :description}
43
+
44
+ form.field_after(:name, :credit_card) {|f| f.input :credit_card}
45
+ form.field_last(:active) {|f| f.input :active}
46
+ end
47
+
48
+ # the first div in a form contains some hidden fields
49
+ assert_select 'form > div:nth-of-type(2) > input.string#user_name'
50
+ assert_select 'form > div:nth-of-type(3) > input.string#user_credit_card'
51
+ assert_select 'form > div:nth-of-type(4) > textarea.text#user_description'
52
+ assert_select 'form > div:nth-of-type(5) > input.boolean#user_active'
53
+ end
54
+
55
+ test "allow prepending elements" do
56
+ with_form_for(@user) do |form|
57
+ form.field(:name) {|f| f.input :name}
58
+ form.field(:description) {|f| f.input :description}
59
+
60
+ form.field_first(:active) {|f| f.input :active}
61
+ form.field_before(:description, :credit_card) {|f| f.input :credit_card}
62
+ end
63
+
64
+ # the first div in a form contains some hidden fields
65
+ assert_select 'form > div:nth-of-type(2) > input.boolean#user_active'
66
+ assert_select 'form > div:nth-of-type(3) > input.string#user_name'
67
+ assert_select 'form > div:nth-of-type(4) > input.string#user_credit_card'
68
+ assert_select 'form > div:nth-of-type(5) > textarea.text#user_description'
69
+ end
70
+
71
+ test "check existence of elements when inserting" do
72
+ assert_raise ArgumentError do
73
+ with_form_for(@user) do |form|
74
+ form.field(:name) {|f| f.input :name}
75
+ form.field_before(:description, :credit_card) {|f| f.input :credit_card}
76
+ end
77
+ end
78
+
79
+ assert_raise ArgumentError do
80
+ with_form_for(@user) do |form|
81
+ form.field(:name) {|f| f.input :name}
82
+ form.field_after(:description, :credit_card) {|f| f.input :credit_card}
83
+ end
84
+ end
85
+ end
86
+
87
+ test "delete field" do
88
+ with_form_for(@user) do |form|
89
+ form.field(:name) {|f| f.input :name}
90
+ form.field(:description) {|f| f.input :description}
91
+
92
+ form.delete(:description)
93
+ end
94
+
95
+ assert_select 'input.string#user_name'
96
+ assert_no_select 'textarea.text#user_description'
97
+ end
98
+ end
@@ -0,0 +1,57 @@
1
+ require File.expand_path('../../../test_helper', __FILE__)
2
+
3
+ class FieldsTest < ActionView::TestCase
4
+ test "render a sub-form" do
5
+ with_form_for(@user) do |form|
6
+ form.field(:name) {|f| f.input :name}
7
+
8
+ form.fields(:tags, :tags, :collection => Tag.all) do |tags|
9
+ tags.field(:name) {|f| f.input :name}
10
+ end
11
+ end
12
+
13
+ assert_select 'input.string#user_name'
14
+
15
+ assert_select 'input.string#user_tags_attributes_0_name'
16
+ assert_select 'input[type=hidden]#user_tags_attributes_0_id'
17
+
18
+ assert_select 'input.string#user_tags_attributes_2_name'
19
+ assert_select 'input[type=hidden]#user_tags_attributes_2_id'
20
+ end
21
+
22
+ test "pass the collection tag as a proc" do
23
+ with_form_for(@user) do |form|
24
+ form.field(:name) {|f| f.input :name}
25
+
26
+ args = lambda{|f| {:collection => Tag.all} }
27
+ form.fields(:tags, :tags, args) do |tags|
28
+ tags.field(:name) {|f| f.input :name}
29
+ end
30
+ end
31
+
32
+ assert_select 'input.string#user_name'
33
+
34
+ assert_select 'input.string#user_tags_attributes_0_name'
35
+ assert_select 'input[type=hidden]#user_tags_attributes_0_id'
36
+
37
+ assert_select 'input.string#user_tags_attributes_2_name'
38
+ assert_select 'input[type=hidden]#user_tags_attributes_2_id'
39
+ end
40
+
41
+ test "append field to sub-form" do
42
+ with_form_for(@user) do |form|
43
+ form.field(:name) {|f| f.input :name}
44
+
45
+ form.fields(:tags, :tags, :collection => Tag.all) do |tags|
46
+ tags.field(:name) {|f| f.input :name}
47
+ end
48
+
49
+ form.fields(:tags).field(:id) {|f| f.input :id}
50
+ end
51
+
52
+ assert_select 'input.string#user_name'
53
+
54
+ assert_select 'input.string#user_tags_attributes_0_name'
55
+ assert_select 'input.string#user_tags_attributes_0_id'
56
+ end
57
+ end
@@ -0,0 +1,53 @@
1
+ require 'test_helper'
2
+
3
+ class FieldsetTest < ActionView::TestCase
4
+ test "create a fieldset" do
5
+ with_form_for(@user) do |form|
6
+ form.fieldset(:payment, :id => "payment") do |fieldset|
7
+ fieldset.legend "These are some fields"
8
+ fieldset.field(:credit_card) {|f| f.input :credit_card}
9
+ end
10
+ end
11
+
12
+ assert_select 'form > fieldset#payment legend', "These are some fields"
13
+ assert_select 'form > fieldset#payment input.string#user_credit_card'
14
+ end
15
+
16
+ test "allow nesting of fieldsets" do
17
+ with_form_for(@user) do |form|
18
+ form.fieldset(:main, :id => 'main') do |outer|
19
+ outer.fieldset(:payment, :id => "payment") do |inner|
20
+ inner.legend "These are some fields"
21
+ inner.field(:credit_card) {|f| f.input :credit_card}
22
+ end
23
+
24
+ outer.field(:name) {|f| f.input :name}
25
+ end
26
+ end
27
+
28
+ assert_no_select 'fieldset#main > legend'
29
+ assert_select 'form > fieldset#main > div > input.string#user_name'
30
+
31
+ assert_select 'form > fieldset#main > fieldset#payment > legend', "These are some fields"
32
+ assert_select 'form > fieldset#main > fieldset#payment input.string#user_credit_card'
33
+ end
34
+
35
+ test "dynamically set args and legend" do
36
+ with_form_for(@user) do |form|
37
+ form.fieldset(:main) do |fieldset|
38
+ # static syntax
39
+ fieldset.args :id => 'main'
40
+ fieldset.legend "These are some fields"
41
+ end
42
+
43
+ form.fieldset(:block) do |fieldset|
44
+ # dynamic block syntax
45
+ fieldset.args{|f| {:id => 'block'} }
46
+ fieldset.legend{|f| "This is a #{f.object.class.name.underscore}"}
47
+ end
48
+ end
49
+
50
+ assert_select 'form > fieldset#main > legend', 'These are some fields'
51
+ assert_select 'form > fieldset#block > legend', 'This is a user'
52
+ end
53
+ end