form_forms 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,19 @@
1
+ # FormForms Change Log
2
+
3
+ ## v0.2.0 - 2012-06-17
4
+
5
+ * Add generic `sub_form` element
6
+ * Add `table_fields` element to render a one-to-many or many-to-many
7
+ association in a table.
8
+
9
+ ## v0.1.0 - 2012-06-16
10
+
11
+ First release containing the basic functionality to create forms:
12
+
13
+ * parent `Form` class
14
+ * `field` to render a single field
15
+ * `fields` to render an association
16
+ * `fieldset` to group elements in a HTML fieldset
17
+ * `block` to group elements in an arbitrary HTML block tag
18
+
19
+ It also introduces the basic `FormRegistry` class
data/README.md CHANGED
@@ -9,7 +9,7 @@ plugins. Thus plugins can easily add, delete and edit form fields without
9
9
  having to override whole views (which are almost impossible to patch) or
10
10
  having to monkey patch existing code which is hard to maintain.
11
11
 
12
- form_forms is originally intended to be used with the simple_form gem and uses
12
+ FormForms is originally intended to be used with the simple_form gem and uses
13
13
  its API in several of its shipped element definitions. While it is possible
14
14
  to not use those and provide custom definitions, we require simple_form as
15
15
  a dependency right now.
@@ -28,17 +28,13 @@ Or install it yourself using
28
28
 
29
29
  # Usage
30
30
 
31
- form_forms is built around the idea that a Rails application is able to
31
+ FormForms is built around the idea that a Rails application is able to
32
32
  define arbitrary forms using a simple yet powerful DSL. These form
33
33
  definitions are typically contained in the `lib` directory and are loaded
34
34
  during initialization. During rendering of a request, the view simply
35
35
  retrieves an existing form definition and renders that form by parameterizing
36
36
  it with some data object (e.g. an ActiveRecord model instance).
37
37
 
38
- To handle several forms, form_forms ships with a simple registry. If you
39
- need a more powerful system, you are of course free to handle your form
40
- objects in any other way.
41
-
42
38
  ## Defining Forms
43
39
 
44
40
  FormForms::Registry[:my_form] = FormForms::Form.new() do |form|
@@ -70,6 +66,22 @@ The render method takes two parameters: the model object that should be used
70
66
  as the base object for the form and a view instance (which can be almost
71
67
  always passed as `self`). The view instance is used to render the form fields.
72
68
 
69
+ ## Form Registry
70
+
71
+ To handle several forms, FormForms ships with a simple registry. If you
72
+ need a more powerful system, you are of course free to handle your form
73
+ objects in any other way.
74
+
75
+ The default registry provides a hash-like interface on the
76
+ `FormForms::Registry` class. You can either directly assign form objects to
77
+ keys there as shown above or you can use the `register` method of all `Form`
78
+ classes as a shorthand:
79
+
80
+ FormForms::Form.register(:my_name) do |form|
81
+ # form definition
82
+ # [...]
83
+ end
84
+
73
85
  ## Adapting an existing form from plugins
74
86
 
75
87
  Once a form is defined, it fields can be added, changed, and removed later on.
@@ -107,7 +119,7 @@ list, preventing it from rendering:
107
119
 
108
120
  # Element Types
109
121
 
110
- form_forms already ships with different element types which allow you to
122
+ FormForms already ships with different element types which allow you to
111
123
  create most of the common form elements. These elements are used to define
112
124
  the actual form body.
113
125
 
@@ -130,12 +142,36 @@ simple_form object. Alternatively to a block, you can also directly pass a
130
142
  string which will be emitted as-is. The usual HTML escape rules apply, i.e.
131
143
  you have to use `html_save` correctly to avoid rendering unsafe data.
132
144
 
145
+ ## `sub_form`
146
+
147
+ Almost all the other element types create a sub form. It allows to group
148
+ several sub elements into a single named element. While the `sub_form` acts
149
+ as a prototype for all other scoping elements (see below) which typically
150
+ surround child elements with HTML block tags during rendering, `sub_form`
151
+ just creates a logical scope in the form and doesn't affect rendering in any
152
+ way.
153
+
154
+ It allows you to group several sub-elements which can then handled as a
155
+ single element.
156
+
157
+ FormForms::Registry[:user] = FormForms::Form.new() do |form|
158
+ form.field(:street) {|f| f.input :street }
159
+ form.field(:city) {|f| f.input :city }
160
+ form.sub_form(:payment) do |sub_form|
161
+ sub_form.field(:credit_card) {|f| f.input :credit_card}
162
+ sub_form.field(:ccv) {|f| f.input :ccv}
163
+ end
164
+ end
165
+
166
+ During rendering, this example will generate the four forms exactly the same
167
+ as if they all would have been defined directly on the form.
168
+
133
169
  ## `fieldset`
134
170
 
135
171
  A fieldset is used to group fields in a single form. During rendering, this
136
- elements will create an HTML `<fieldset>` tag and a `<legend>`. As a fieldset
137
- naturally contains other fields, its generator block can be used to define
138
- fields.
172
+ elements will create an HTML `<fieldset>` tag and a `<legend>` around its
173
+ sub-elements. As a fieldset naturally contains other fields, its generator
174
+ block can be used to define fields.
139
175
 
140
176
  FormForms::Registry[:user] = FormForms::Form.new() do |form|
141
177
  form.field(:street) {|f| f.input :street }
@@ -167,11 +203,18 @@ markup the form using custom CSS rules. This element works similar to the
167
203
 
168
204
  FormForms::Registry[:user] = FormForms::Form.new() do |form|
169
205
  form.field(:street) {|f| f.input :street }
170
- form.block(:box, :class => "red-and-blinky") do |block|
206
+ form.block(:box, :div, :class => "red-and-blinky") do |block|
171
207
  block.field(:sell_your_soul) {|f| f.input :sell_your_soul}
172
208
  end
173
209
  end
174
210
 
211
+ Here, the block element takes the name of the newly created element, the type
212
+ of HTML tag to create and a hash of options to pass to the `content_tag`
213
+ helper of ´Rails which creates the tag internally.
214
+
215
+ The generator block creates a new element scope similar to the fieldset
216
+ element.
217
+
175
218
  ## `fields`
176
219
 
177
220
  Using fields, you can create sub-forms for association of the model object.
@@ -195,19 +238,86 @@ rendered. For the example above, the `User` model is defined as follows:
195
238
  end
196
239
 
197
240
  The third argument is an options hash which is passed to association render
198
- function of simple_form. In our example, we pass the `:collection` attribute
199
- which instructs simple_form to render a select box containing the elements of
200
- the passed collection.
241
+ function of simple_form. And finally we have the generator block which works
242
+ the same as for fieldsets and blocks.
201
243
 
202
- Here we have to do a little trick. If we simple pass the array here as in
244
+ In our example above, we pass the `:collection` attribute in the options
245
+ which instructs simple_form to render a select box containing the elements
246
+ of the passed collection. Here we have to do a little trick. If we simple
247
+ pass the array of tags here as in
203
248
 
204
249
  form.fields(:tags, :tags, :collection => Tag.all) do |tags|
205
250
 
206
251
  the `Tags.all` would be evaluated just once, during the initialization of the
207
- application. New tags would not be included. To fix this, we pass a
208
- lambda block which is evaluated each time again during the form rendering.
209
- This lambda is expected to return an array of options to the `association`
210
- method of simple_form.
252
+ application. New tags created later would not be included. To fix this, we
253
+ pass a `lambda` block which is evaluated each time again during the form
254
+ rendering. This lambda is expected to return a hash of options which is
255
+ passed to the `association` method of simple_form.
256
+
257
+ ## `table_fields`
258
+
259
+ The `table_fields` element allows to render a nested association in a table.
260
+ This is especially suitable for editing a large amount of nested objects.
261
+
262
+ For additional forms functionality, you might want to use
263
+ [cocoon](https://github.com/nathanvda/cocoon) which adds some JQuery functions
264
+ to manipulate table rows in the browser (e.g. add or delete rows).
265
+
266
+ FormForms::Registry[:user] = FormForms::Form.new() do |form|
267
+ form.field(:name) {|f| f.input :name}
268
+
269
+ form.table_fields(:companies, :companies) do |table|
270
+ table.header do |header|
271
+ header.field(:name) {|f| "Name" }
272
+ header.field(:location) {|f| "Location" }
273
+ header.field(:description) {|f| "Description" }
274
+ header.field(:actions, :class => "actions") {|f| "Actions" }
275
+ end
276
+
277
+ # each data row gets these attributes
278
+ table.row_args({:class => "nested-fields"})
279
+
280
+ table.field(:name) {|f| f.input :name}
281
+ table.field(:location) {|f| f.input :location}
282
+ table.field(:description) {|f| f.input :description}
283
+
284
+ table.sub_form(:actions) do |actions|
285
+ # Each cell in the actions column gets a custom class
286
+ actions.cell_args ({:class => "actions"})
287
+
288
+ actions.field(:delete) {|f| content_tag(:a, :href => "#") { "Delete" } }
289
+ actions.field(:id) {|f| f.hidden_field :id }
290
+ end
291
+ end
292
+ end
293
+
294
+ For rendering a tabular form for an association, call `table_fields` with the
295
+ form element name and the name of the association. Optionally you can add
296
+ additional options which get passed to the simple_form `association` method.
297
+
298
+ In the `table_fields` generator, you have to define header and body fields.
299
+ You can use and element type for each of the fields. You just have to make
300
+ sure that the number of elements in the header and the body matches.
301
+
302
+ The `table_fields` environment slightly adapts all nested elements. To be
303
+ able to adapt the generated `<th` and `<td>` tags, each element has an
304
+ additional property called `cell_args`. If you set it to a hash, you can set
305
+ any HTML attributes of the generated cell tag. As before, you can also pass a
306
+ proc which return a hash for lazy evaluation.
307
+
308
+ Each element in the table body gets automatically wrapped in a `<td>` tag.
309
+ Each element in the association collection is rendered as s single row.
310
+
311
+ To customize the table, you can use the following properties:
312
+
313
+ * `table.args`: Hash of additional arguments for specifying the simple_form association.
314
+ * `table.table_args`: Hash of HTML attributes of the `<table>` tag.
315
+ * `table.row_args`: Hash of HTML attributes of each `<tr>` tag.
316
+ * `table.<element>.cell_args`: Hash of HTML attributes of the `<td>` tag for a field in a row.
317
+
318
+ * `table.header`
319
+ * `table.header.row_args`: Hash of HTML attributes of the header row
320
+ * `table.header.<element>.cell_args`: Hash of HTML attributes of the `<th>` tag for a field in the header row
211
321
 
212
322
  # Development
213
323
 
@@ -1,5 +1,10 @@
1
1
  require 'form_forms/elements/base_element'
2
+ require 'form_forms/elements/sub_form'
2
3
  require 'form_forms/elements/block'
3
4
  require 'form_forms/elements/field'
4
5
  require 'form_forms/elements/fields'
5
6
  require 'form_forms/elements/fieldset'
7
+
8
+ require 'form_forms/elements/table_fields'
9
+ require 'form_forms/elements/table_header'
10
+ require 'form_forms/elements/table_header_field'
@@ -58,7 +58,8 @@ module FormForms
58
58
  # # => [:subject, :name, :description]
59
59
 
60
60
  def self.allowed_sub_element(type, klass=nil)
61
- klass ||= "::FormForms::Elements::#{type.to_s.classify}"
61
+ klass ||= element_class_name(type)
62
+ klass = klass.name if klass.is_a?(Class)
62
63
 
63
64
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
64
65
  def #{type}(name, *args, &block)
@@ -86,6 +87,10 @@ module FormForms
86
87
  RUBY
87
88
  end
88
89
 
90
+ def self.element_class_name(type)
91
+ "::FormForms::Elements::#{type.to_s.classify}"
92
+ end
93
+
89
94
  # Define a property of the element. Properties can either be given as
90
95
  # a block, similar to the fields, or as a static object. Internally,
91
96
  # we always use the block form.
@@ -1,12 +1,6 @@
1
1
  module FormForms
2
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
-
3
+ class Block < SubForm
10
4
  def initialize(element, args = {})
11
5
  @element = element.to_sym
12
6
  self.args args
@@ -19,13 +19,15 @@ module FormForms
19
19
  # end
20
20
  # end
21
21
  # end
22
- class Field
22
+ class Field < BaseElement
23
23
  def initialize(&generator)
24
- @generator = generator
24
+ self.generator generator
25
25
  end
26
26
 
27
+ property :generator
28
+
27
29
  def render(builder, view)
28
- view.instance_exec(builder, &@generator)
30
+ eval_property(:generator, builder, view)
29
31
  end
30
32
  end
31
33
  end
@@ -1,13 +1,7 @@
1
1
  module FormForms
2
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={})
3
+ class Fields < SubForm
4
+ def initialize(association, form_args={})
11
5
  self.association association
12
6
  self.args form_args
13
7
  super
@@ -20,8 +14,8 @@ module FormForms
20
14
  association = eval_property(:association, builder, view)
21
15
  form_args = eval_property(:args, builder, view)
22
16
 
23
- builder.association(association, form_args) do |sub|
24
- render_elements(sub, view)
17
+ builder.association(association, form_args) do |sub_builder|
18
+ super(sub_builder, view)
25
19
  end
26
20
  end
27
21
  end
@@ -1,11 +1,14 @@
1
1
  module FormForms
2
2
  module Elements
3
- class Fieldset < Block
4
- def initialize(fieldset_args={}, &generator)
3
+ class Fieldset < SubForm
4
+ def initialize(args={}, &generator)
5
5
  self.legend nil
6
- super(:fieldset, fieldset_args, &generator)
6
+ self.args args
7
+
8
+ super
7
9
  end
8
10
 
11
+ property :args
9
12
  property :legend
10
13
 
11
14
  # Generate a fielset with a legend
@@ -0,0 +1,12 @@
1
+ module FormForms
2
+ module Elements
3
+ class SubForm < BaseElement
4
+ allowed_sub_element :field
5
+ allowed_sub_element :sub_form
6
+ allowed_sub_element :block
7
+ allowed_sub_element :fieldset
8
+ allowed_sub_element :fields
9
+ allowed_sub_element :table_fields
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,84 @@
1
+ module FormForms
2
+ module Elements
3
+ class TableFields < BaseElement
4
+ protected
5
+
6
+ # For an allowed_sub_element, create a subclass which renders the
7
+ # element as a table cell. It wrapps the rendering of the original
8
+ # element in an HTML td tag.
9
+ # To allow to customize the tag, it adds a new property called
10
+ # +cell_args+ to the subclass which allows to set additional arguments
11
+ # to the +td+ tag.
12
+ def self.wrap_sub_element(type)
13
+ parent = element_class_name(type)
14
+
15
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
16
+ class #{parent.demodulize} < #{parent}
17
+ def initialize(*args, &block)
18
+ self.cell_args {}
19
+ super
20
+ end
21
+
22
+ property :cell_args
23
+
24
+ def render(builder, view)
25
+ cell_args = eval_property(:cell_args, builder, view)
26
+ view.content_tag(:td, cell_args) do
27
+ super
28
+ end
29
+ end
30
+ end
31
+ RUBY
32
+
33
+ "FormForms::Elements::TableFields::#{parent.demodulize}"
34
+ end
35
+
36
+ public
37
+ allowed_sub_element :field, wrap_sub_element(:field)
38
+ allowed_sub_element :sub_form, wrap_sub_element(:sub_form)
39
+ allowed_sub_element :block, wrap_sub_element(:block)
40
+ allowed_sub_element :fieldset, wrap_sub_element(:fieldset)
41
+ allowed_sub_element :fields, wrap_sub_element(:fields)
42
+
43
+ def initialize(association, form_args={})
44
+ self.association association
45
+ self.args form_args
46
+ self.table_args {}
47
+ self.row_args {}
48
+
49
+ super
50
+ end
51
+
52
+ property :association
53
+ property :args
54
+ property :table_args
55
+ property :row_args
56
+
57
+ def header(row_args = {}, &generator)
58
+ @header = TableHeader.new(row_args, &generator) if block_given?
59
+ @header
60
+ end
61
+
62
+ def render(builder, view)
63
+ association = eval_property(:association, builder, view)
64
+ form_args = eval_property(:args, builder, view)
65
+ table_args = eval_property(:table_args, builder, view)
66
+
67
+ view.content_tag(:table, table_args) do
68
+ # render the header row
69
+ view.concat view.content_tag(:thead, header.render(builder, view)) if @header
70
+
71
+ # render the table body
72
+ body = builder.association(association, form_args) do |sub_builder|
73
+ row_args = eval_property(:row_args, sub_builder, view)
74
+ view.content_tag(:tr, row_args) do
75
+ super(sub_builder, view)
76
+ end
77
+ end
78
+ view.concat view.content_tag(:tbody, body)
79
+ end
80
+ end
81
+
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,23 @@
1
+ module FormForms
2
+ module Elements
3
+ class TableHeader < BaseElement
4
+ allowed_sub_element :field, element_class_name(:table_header_field)
5
+
6
+ def initialize(row_args={})
7
+ self.row_args row_args
8
+ super
9
+ end
10
+
11
+ property :row_args
12
+
13
+ def render(builder, view)
14
+ return "" if self.elements.empty?
15
+
16
+ row_args = eval_property(:row_args, builder, view)
17
+ view.content_tag(:tr, row_args) do
18
+ super
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,20 @@
1
+ module FormForms
2
+ module Elements
3
+ class TableHeaderField < Field
4
+ def initialize(cell_args={}, &generator)
5
+ self.cell_args cell_args
6
+ super(&generator)
7
+ end
8
+
9
+ property :cell_args
10
+
11
+ def render(builder, view)
12
+ cell_args = eval_property(:cell_args, builder, view)
13
+
14
+ view.content_tag(:th, cell_args) do
15
+ super
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -6,6 +6,7 @@ module FormForms
6
6
  # form builder object
7
7
  class Form < BaseForm
8
8
  allowed_sub_element :field
9
+ allowed_sub_element :sub_form
9
10
  allowed_sub_element :block
10
11
  allowed_sub_element :fieldset
11
12
  allowed_sub_element :fields
@@ -1,3 +1,3 @@
1
1
  module Formforms
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -95,4 +95,15 @@ class FieldTest < ActionView::TestCase
95
95
  assert_select 'input.string#user_name'
96
96
  assert_no_select 'textarea.text#user_description'
97
97
  end
98
+
99
+ test "replace a field's generator" do
100
+ with_form_for(@user) do |form|
101
+ form.field(:name) {|f| f.input :name}
102
+
103
+ form.field(:name).generator {|f| f.input :description}
104
+ end
105
+
106
+ assert_no_select 'input.string#user_name'
107
+ assert_select 'textarea.text#user_description'
108
+ end
98
109
  end
@@ -0,0 +1,18 @@
1
+ require 'test_helper'
2
+
3
+ class SubFormTest < ActionView::TestCase
4
+ test "create a subform" do
5
+ with_form_for(@user) do |form|
6
+ form.field(:name) {|f| f.input :name}
7
+
8
+ form.sub_form(:credit) do |block|
9
+ block.field(:credit_card) {|f| f.input :credit_card}
10
+ block.field(:credit_limit) {|f| f.input :credit_limit}
11
+ end
12
+ end
13
+
14
+ assert_select 'form > div:nth-of-type(2) > input.string#user_name'
15
+ assert_select 'form > div:nth-of-type(3) > input.string#user_credit_card'
16
+ assert_select 'form > div:nth-of-type(4) > input.decimal#user_credit_limit'
17
+ end
18
+ end
@@ -0,0 +1,49 @@
1
+ require File.expand_path('../../../test_helper', __FILE__)
2
+
3
+ class TableFieldsTest < ActionView::TestCase
4
+ test "render a sub-form as a table" do
5
+ with_form_for(@user) do |form|
6
+ form.field(:name) {|f| f.input :name}
7
+
8
+ form.table_fields(:companies, :companies) do |table|
9
+ table.header do |header|
10
+ header.field(:name) {|f| "Name" }
11
+ header.field(:location) {|f| "Location" }
12
+ header.field(:description) {|f| "Description" }
13
+ header.field(:actions, :class => "actions") {|f| "Actions" }
14
+ end
15
+
16
+ table.row_args({:class => "nested-fields"})
17
+
18
+ table.field(:name) {|f| f.input :name}
19
+ table.field(:location) {|f| f.input :location}
20
+ table.field(:description) {|f| f.input :description}
21
+ table.sub_form(:actions) do |actions|
22
+ actions.field(:delete) {|f| content_tag(:a, :href => "#") { "Delete" } }
23
+ actions.field(:id) {|f| f.hidden_field :id }
24
+ end
25
+ end
26
+ end
27
+
28
+ assert_select 'form > div:nth-of-type(2) > input.string#user_name'
29
+
30
+ # Header rendered correctly?
31
+ assert_select 'form > table'
32
+ assert_select 'table > thead > tr > th:nth-of-type(1)', 'Name'
33
+ assert_select 'table > thead > tr > th:nth-of-type(2)', 'Location'
34
+ assert_select 'table > thead > tr > th:nth-of-type(4).actions', 'Actions'
35
+
36
+ # All rows fully rendered
37
+ (1..3).each do |i|
38
+ assert_select "table > tbody > tr:nth-of-type(#{i}) > td:nth-of-type(1) input.string#user_companies_attributes_#{i-1}_name[value='Company #{i}']"
39
+ assert_select "table > tbody > tr:nth-of-type(#{i}) > td:nth-of-type(2) textarea.text#user_companies_attributes_#{i-1}_location", Company.all[i-1].location
40
+ assert_select "table > tbody > tr:nth-of-type(#{i}) > td:nth-of-type(3) textarea.text#user_companies_attributes_#{i-1}_description", ""
41
+
42
+ assert_select "table > tbody > tr:nth-of-type(#{i}) > td:nth-of-type(4) a[href='#']", "Delete"
43
+ assert_select "table > tbody > tr:nth-of-type(#{i}) > td:nth-of-type(4) input#user_companies_attributes_#{i-1}_id[type=hidden][value=#{i}]"
44
+ end
45
+
46
+ # No more rows than expected
47
+ assert_no_select 'table > tbody > tr:nth-of-type(4)'
48
+ end
49
+ end
@@ -8,16 +8,17 @@ class Column < ColumnParent
8
8
  end
9
9
  end
10
10
 
11
- Association = Struct.new(:klass, :name, :macro, :options)
11
+ Association = Struct.new(:klass, :name, :macro, :options) unless defined?(Association)
12
12
 
13
13
  # Always use the same parent, even after multiple requires
14
- CompanyParent = Struct.new(:id, :name) unless defined?(CompanyParent)
14
+ CompanyParent = Struct.new(:id, :name, :location, :description) unless defined?(CompanyParent)
15
15
  class Company < CompanyParent
16
16
  extend ActiveModel::Naming
17
17
  include ActiveModel::Conversion
18
18
 
19
19
  def self.all(options={})
20
- all = (1..3).map{|i| Company.new(i, "Company #{i}")}
20
+ streets = ["Main Street", "Second Street", "Evergreen Terrace"]
21
+ all = (1..3).map{|i| Company.new(i, "Company #{i}", streets[i-1])}
21
22
  return [all.first] if options[:conditions].present?
22
23
  return [all.last] if options[:order].present?
23
24
  return all[0..1] if options[:include].present?
@@ -29,6 +30,15 @@ class Company < CompanyParent
29
30
  (a || {}).merge(b || {})
30
31
  end
31
32
 
33
+ def column_for_attribute(attribute)
34
+ column_type, limit = case attribute.to_sym
35
+ when :name then [:string, 100]
36
+ when :location, :description then [:text, 200]
37
+ end
38
+ Column.new(attribute, column_type, limit)
39
+ end
40
+
41
+
32
42
  def persisted?
33
43
  true
34
44
  end
@@ -48,7 +58,8 @@ class User
48
58
  :description, :created_at, :updated_at, :credit_limit, :password, :url,
49
59
  :delivery_time, :born_at, :special_company_id, :country, :tags, :tag_ids,
50
60
  :avatar, :home_picture, :email, :status, :residence_country, :phone_number,
51
- :post_count, :lock_version, :amount, :attempts, :action, :credit_card, :gender
61
+ :post_count, :lock_version, :amount, :attempts, :action, :credit_card,
62
+ :gender, :company_ids, :companies
52
63
 
53
64
  def initialize(options={})
54
65
  @new_record = false
@@ -65,9 +76,16 @@ class User
65
76
  !@new_record
66
77
  end
67
78
 
79
+ def companies
80
+ Company.all
81
+ end
82
+
68
83
  def company_attributes=(*)
69
84
  end
70
85
 
86
+ def companies_attributes=(*)
87
+ end
88
+
71
89
  def tags_attributes=(*)
72
90
  end
73
91
 
@@ -109,6 +127,8 @@ class User
109
127
  case association
110
128
  when :company
111
129
  Association.new(Company, association, :belongs_to, {})
130
+ when :companies
131
+ Association.new(Company, association, :has_many, {})
112
132
  when :tags
113
133
  Association.new(Tag, association, :has_many, {})
114
134
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: form_forms
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-16 00:00:00.000000000 Z
12
+ date: 2012-06-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
16
- requirement: &2163535820 !ruby/object:Gem::Requirement
16
+ requirement: &2163568860 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '3.0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2163535820
24
+ version_requirements: *2163568860
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: actionpack
27
- requirement: &2163535320 !ruby/object:Gem::Requirement
27
+ requirement: &2163568360 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '3.0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *2163535320
35
+ version_requirements: *2163568360
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: simple_form
38
- requirement: &2163534940 !ruby/object:Gem::Requirement
38
+ requirement: &2163567980 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *2163534940
46
+ version_requirements: *2163567980
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: activemodel
49
- requirement: &2163534400 !ruby/object:Gem::Requirement
49
+ requirement: &2163567440 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,7 +54,7 @@ dependencies:
54
54
  version: '3.0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *2163534400
57
+ version_requirements: *2163567440
58
58
  description: Configurable forms for Rails
59
59
  email:
60
60
  - hjust@meine-er.de
@@ -64,6 +64,7 @@ extra_rdoc_files: []
64
64
  files:
65
65
  - .gitignore
66
66
  - .travis.yml
67
+ - CHANGELOG.md
67
68
  - Gemfile
68
69
  - LICENSE
69
70
  - README.md
@@ -79,6 +80,10 @@ files:
79
80
  - lib/form_forms/elements/field.rb
80
81
  - lib/form_forms/elements/fields.rb
81
82
  - lib/form_forms/elements/fieldset.rb
83
+ - lib/form_forms/elements/sub_form.rb
84
+ - lib/form_forms/elements/table_fields.rb
85
+ - lib/form_forms/elements/table_header.rb
86
+ - lib/form_forms/elements/table_header_field.rb
82
87
  - lib/form_forms/form_registry.rb
83
88
  - lib/form_forms/forms.rb
84
89
  - lib/form_forms/forms/base_form.rb
@@ -88,6 +93,8 @@ files:
88
93
  - test/form_forms/elements/field_test.rb
89
94
  - test/form_forms/elements/fields_test.rb
90
95
  - test/form_forms/elements/fieldset_test.rb
96
+ - test/form_forms/elements/sub_form_test.rb
97
+ - test/form_forms/elements/table_fields_test.rb
91
98
  - test/form_forms/form_registry_test.rb
92
99
  - test/form_forms/forms/form_test.rb
93
100
  - test/support/misc_helpers.rb
@@ -123,6 +130,8 @@ test_files:
123
130
  - test/form_forms/elements/field_test.rb
124
131
  - test/form_forms/elements/fields_test.rb
125
132
  - test/form_forms/elements/fieldset_test.rb
133
+ - test/form_forms/elements/sub_form_test.rb
134
+ - test/form_forms/elements/table_fields_test.rb
126
135
  - test/form_forms/form_registry_test.rb
127
136
  - test/form_forms/forms/form_test.rb
128
137
  - test/support/misc_helpers.rb