formize 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Brice Texier
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,74 @@
1
+ = Formize
2
+
3
+ Simple form DSL with dynamic interactions for Rails.
4
+
5
+ == Installation
6
+
7
+ Add it to your Gemfile:
8
+ gem "formize"
9
+
10
+ It's not necessary, but I recommend to use HAML with it for cleaner views:
11
+ gem "haml"
12
+
13
+ == Usage
14
+
15
+ In controller:
16
+
17
+ class OrdersController < ApplicationController
18
+ # Generates default helpers method and a controller method :formize
19
+ # for a model Order.
20
+ formize
21
+
22
+ # Personnalized example
23
+ formize do
24
+ field :number
25
+ field :created_on
26
+ field :client
27
+ field_set :addresses, :depend_on=>:client do
28
+ field :default_contact, :choices=>:contacts, :source=>:client
29
+ field :delivery_contact, :choices=>:contacts, :source=>:client
30
+ field :invoice_contact, :choices=>:contacts, :source=>:client
31
+ end
32
+ field_set :track do
33
+ field :responsible
34
+ field :department
35
+ end
36
+ end
37
+
38
+ # Moreover, with a specified model
39
+ formize(:lines, :model=>:order_lines)
40
+
41
+ end
42
+
43
+ In views:
44
+
45
+ # app/views/orders/_form.html.haml
46
+ =formize_form
47
+
48
+ or:
49
+
50
+ # app/views/orders/_form.html.haml
51
+ =form_tag do
52
+ =formize_fields
53
+
54
+ or:
55
+
56
+ # app/views/orders/_form.html.haml
57
+ =formize_form :lines
58
+
59
+
60
+ == Contributing to Formize
61
+
62
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
63
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
64
+ * Fork the project
65
+ * Start a feature/bugfix branch
66
+ * Commit and push until you are happy with your contribution
67
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
68
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
69
+
70
+ == Copyright
71
+
72
+ Copyright (c) 2011 Brice Texier. See LICENSE.txt for
73
+ further details.
74
+
data/Rakefile ADDED
@@ -0,0 +1,63 @@
1
+ # encoding: utf-8
2
+ # Used for a bug with ruby 1.9.1
3
+ # http://rubyforge.org/tracker/index.php?func=detail&aid=28920&group_id=1513&atid=5921
4
+ require 'psych'
5
+
6
+ require 'rubygems'
7
+ # require 'rake'
8
+ gem 'rake', '0.8.7'
9
+
10
+ require 'jeweler'
11
+ Jeweler::Tasks.new do |gem|
12
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
13
+ gem.name = "formize"
14
+ gem.homepage = "http://github.com/burisu/formize"
15
+ gem.license = "MIT"
16
+ gem.summary = "Simple form DSL with dynamic interactions for Rails"
17
+ gem.description = "Like simple_form or formtastic, it aims to handle easily forms but taking in account AJAX and HTML5 on depending fields mainly."
18
+ gem.email = "brice.texier@ekylibre.org"
19
+ gem.authors = ["Brice Texier"]
20
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
21
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
22
+ # gem.add_runtime_dependency 'jabber4r', '> 0.1'
23
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
24
+ # gem.add_development_dependency "bundler", "~> 1.0.0"
25
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
26
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
27
+ # gem.add_runtime_dependency 'jabber4r', '> 0.1'
28
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
29
+ gem.add_development_dependency "jeweler", "~> 1.6.4"
30
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
31
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
32
+ # gem.add_runtime_dependency 'jabber4r', '> 0.1'
33
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
34
+ gem.add_development_dependency "rcov", ">= 0"
35
+ gem.add_development_dependency "actionpack", ">= 0"
36
+ end
37
+ Jeweler::RubygemsDotOrgTasks.new
38
+
39
+ require 'rake/testtask'
40
+ Rake::TestTask.new(:test) do |test|
41
+ test.libs << 'lib' << 'test'
42
+ test.pattern = 'test/**/test_*.rb'
43
+ test.verbose = true
44
+ end
45
+
46
+ require 'rcov/rcovtask'
47
+ Rcov::RcovTask.new do |test|
48
+ test.libs << 'test'
49
+ test.pattern = 'test/**/test_*.rb'
50
+ test.verbose = true
51
+ test.rcov_opts << '--exclude "gems/*"'
52
+ end
53
+
54
+ task :default => :test
55
+
56
+ require 'rake/rdoctask'
57
+ Rake::RDocTask.new do |rdoc|
58
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
59
+ rdoc.rdoc_dir = 'rdoc'
60
+ rdoc.title = "Formize #{version}"
61
+ rdoc.rdoc_files.include('README*')
62
+ rdoc.rdoc_files.include('lib/**/*.rb')
63
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.2
@@ -0,0 +1,399 @@
1
+ /*jslint devel: true, browser: true, sloppy: true, vars: true, white: true, maxerr: 50, indent: 4 */
2
+
3
+ var Formize = {};
4
+
5
+ Formize.Overlay = {
6
+
7
+ count : 0,
8
+
9
+ add : function (body) {
10
+ body = body || document.body || document.getElementsByTagName("BODY")[0];
11
+ var dims = document.viewport.getDimensions();
12
+ var height = dims.height, width = dims.width, overlay = $('overlay');
13
+ if (overlay === null) {
14
+ overlay = new Element('div', {id: 'overlay', style: 'position:fixed; top:0; left 0; width:'+width+'px; height: '+height+'px; opacity: 0.5'});
15
+ body.appendChild(overlay);
16
+ }
17
+ this.count += 1;
18
+ overlay.setStyle({'z-index': this.z_index()});
19
+ return overlay;
20
+ },
21
+
22
+ remove: function() {
23
+ this.count -= 1;
24
+ var overlay = $('overlay');
25
+ if (overlay !== null) {
26
+ if (this.count <= 0) {
27
+ overlay.remove();
28
+ } else {
29
+ overlay.setStyle({'z-index': this.z_index()});
30
+ }
31
+ }
32
+ return this.count;
33
+ },
34
+
35
+ // Computes a big z-index with interval in order to intercalate dialogs
36
+ z_index: function() {
37
+ return (10*this.count + 10000);
38
+ }
39
+ };
40
+
41
+
42
+ Formize.Dialog = {
43
+
44
+ /* Opens a div like a virtual popup*/
45
+ open: function (url, updated, ratio) {
46
+ var body = document.body || document.getElementsByTagName("BODY")[0];
47
+ var dims = document.viewport.getDimensions();
48
+ var height = dims.height;
49
+ var width = dims.width;
50
+ var dialog_id = 'dialog'+Formize.Overlay.count;
51
+ if (isNaN(ratio)) { ratio = 0.6; }
52
+
53
+ Formize.Overlay.add();
54
+
55
+ return new Ajax.Request(url, {
56
+ method: 'get',
57
+ parameters: {dialog: dialog_id},
58
+ evalScripts: true,
59
+ onSuccess: function(response) {
60
+ var dialog = new Element('div', {id: dialog_id, 'data-ratio': ratio, 'data-dialog-update': updated, flex: '1', 'class': 'dialog', style: 'z-index:'+(Formize.Overlay.z_index()+1)+'; position:fixed; opacity: 1'});
61
+ body.appendChild(dialog);
62
+ dialog.update(response.responseText);
63
+ var w = ratio*width;
64
+ var h = ratio*height;
65
+ if (ratio <= 0) {
66
+ var dialogDims = dialog.getDimensions();
67
+ w = dialogDims.width;
68
+ h = dialogDims.height;
69
+ }
70
+ dialog.setStyle('left:'+((width-w)/2)+'px; top:'+((height-h)/2)+'px; width:'+w+'px; height: '+h+'px');
71
+ return dialog.resize(w, h);
72
+ },
73
+ onFailure: function(response) {
74
+ alert("FAILURE (Error "+response.status+"): "+response.reponseText);
75
+ Formize.Overlay.remove();
76
+ }
77
+ });
78
+ },
79
+
80
+ /* Close a virtual popup */
81
+ close: function (dialog) {
82
+ dialog = $(dialog);
83
+ dialog.remove();
84
+ Formize.Overlay.remove();
85
+ return true;
86
+ }
87
+
88
+
89
+ };
90
+
91
+
92
+ Formize.Partials = {
93
+
94
+ refresh: function (event, element) {
95
+ var dependents = element.readAttribute('data-dependents').split(',');
96
+ var params = new Hash();
97
+ if (element.value !== null && element.value !== undefined) {
98
+ params.set(element.id, element.value);
99
+ dependents.each(function(item_id) {
100
+ // Replaces element
101
+ var item = $(item_id);
102
+ if (item) {
103
+ var url = item.readAttribute('data-refresh');
104
+ if (url !== null) {
105
+ new Ajax.Request(url, {
106
+ method: 'get',
107
+ asynchronous:true,
108
+ evalScripts:true,
109
+ parameters: params,
110
+ onSuccess: function(response) {
111
+ item.replace(response.responseText);
112
+ $(item_id).fire("dom:loaded");
113
+ },
114
+ onFailure: function(response) {
115
+ alert("ERROR FAILURE\n"+response.status+" "+response.statusText);
116
+ }
117
+ });
118
+ }
119
+ }
120
+ });
121
+ return true;
122
+ }
123
+ },
124
+
125
+ submitDialogForm: function(event, form) {
126
+ var dialog_id = form.readAttribute('data-dialog');
127
+ var dialog = $(dialog_id);
128
+
129
+ var field = new Element('input', { type: 'hidden', name: 'dialog', value: dialog_id });
130
+ form.insert(field);
131
+
132
+ new Ajax.Request(form.readAttribute('action'), {
133
+ method: form.readAttribute('method') || 'post',
134
+ parameters: Form.serialize(form),
135
+ asynchronous: true,
136
+ evalScripts: true,
137
+ onLoaded: function(request){ form.fire("layout:change"); },
138
+ onSuccess: function(request){
139
+ if (request.responseJSON === null) {
140
+ // No return => validation error
141
+ dialog.update(request.responseText);
142
+ dialog.fire("layout:change");
143
+ } else {
144
+ // Refresh element with its refresh URL
145
+ var updated =$(dialog.readAttribute('data-dialog-update'));
146
+ if (updated !== null) {
147
+ var url = updated.readAttribute('data-refresh');
148
+ new Ajax.Request(url, {
149
+ method: 'GET',
150
+ asynchronous:true,
151
+ evalScripts:true,
152
+ parameters: {selected: request.responseJSON.id},
153
+ onSuccess: function(request) {
154
+ updated.replace(request.responseText);
155
+ updated.fire("layout:change");
156
+ }
157
+ });
158
+ }
159
+ // Close dialog
160
+ Formize.Dialog.close(dialog);
161
+ }
162
+ }
163
+ });
164
+ event.stop();
165
+ return false;
166
+ },
167
+
168
+ uniqueID: function() {
169
+ var uid = 'u'+((new Date()).getTime() + "" + Math.floor(Math.random() * 1000000)).substr(0, 18);
170
+ return uid;
171
+ },
172
+
173
+ initializeUnroll: function(element) {
174
+ var choices, paramName;
175
+ if (element.valueField !== null && element.valueField !== undefined) {
176
+ return false;
177
+ }
178
+
179
+ choices = element.readAttribute('data-choices-container');
180
+ if (choices === null) {
181
+ choices = new Element('div', {
182
+ 'id': this.uniqueID(),
183
+ 'class': "unroll-choices",
184
+ 'style': "display: none"
185
+ });
186
+ element.insert({after: choices});
187
+ element.writeAttribute('data-choices-container', choices.id);
188
+ }
189
+
190
+ element.unrollCache = element.value;
191
+ element.valueField = $(element.readAttribute('data-value-container'));
192
+ if (element.valueField === null) {
193
+ alert('An input '+element.id+' with a "data-unroll" attribute must contain a "data-value-container" attribute');
194
+ }
195
+ element.maxResize = parseInt(element.readAttribute('data-max-resize'));
196
+ if (isNaN(element.maxResize) || element.maxResize === 0) { element.maxResize = 64; }
197
+ element.size = (element.unrollCache.length > element.maxResize ? element.maxResize : element.unrollCache.length);
198
+
199
+ new Ajax.Autocompleter(element, choices, element.readAttribute('data-unroll'), {
200
+ method: 'GET',
201
+ paramName: 'search',
202
+ afterUpdateElement: function(element, selected) {
203
+ var model_id = /(\d+)$/.exec(selected.id)[1];
204
+ element.valueField.value = model_id;
205
+ element.valueField.fire("emulated:change");
206
+ element.unrollCache = element.value;
207
+ element.size = (element.unrollCache.length > element.maxResize ? element.maxResize : element.unrollCache.length);
208
+ }
209
+ });
210
+ }
211
+
212
+ };
213
+
214
+
215
+ (function() {
216
+ "use strict";
217
+
218
+ // Refreshes dependent elements
219
+ document.on("change", "*[data-dependents]", Formize.Partials.refresh);
220
+ document.on("emulated:change", "*[data-dependents]", Formize.Partials.refresh);
221
+
222
+ // Opens a dialog for a ressource creation
223
+ document.on("click", "a[data-add-item]", function(event, element) {
224
+ var list_id = element.readAttribute('data-add-item');
225
+ var url = element.readAttribute('href');
226
+ Formize.Dialog.open(url, list_id);
227
+ event.stop();
228
+ });
229
+
230
+ // Closes a dialog
231
+ document.on("click", "a[data-close-dialog]", function(event, element) {
232
+ var dialog_id = element.readAttribute('data-close-dialog');
233
+ Formize.Dialog.close(dialog_id);
234
+ event.stop();
235
+ });
236
+
237
+ // Submits dialog forms
238
+ document.on("submit", "form[data-dialog]", Formize.Partials.submitDialogForm);
239
+
240
+ // Manage unroll
241
+ // this is the only found way to work with dom:loaded
242
+
243
+ Event.observe(window, "dom:loaded", function(event) {
244
+ $$('input[data-unroll]').each(function(element) {
245
+ Formize.Partials.initializeUnroll(element);
246
+ });
247
+ });
248
+
249
+ document.on("focusin", "input[data-unroll]", function(event, element) {
250
+ if (element.unrollCache === undefined) {
251
+ element.unrollCache = element.value;
252
+ }
253
+ });
254
+
255
+
256
+ // if (1) {
257
+ // if (this.value != this.unrollCache) {
258
+ // this.valueField.value = '';
259
+ // }
260
+ // } else {
261
+ // this.value = this.unrollCache;
262
+ // }
263
+ document.on("change", "input[data-unroll]", function(event, element) {
264
+ window.setTimeout(function () {
265
+ if (this.value != this.unrollCache) {
266
+ this.valueField.value = '';
267
+ this.valueField.fire("emulated:change");
268
+ }
269
+ }.bind(element), 200);
270
+ });
271
+
272
+ document.on("keypress", "input[data-unroll]", function(event, element) {
273
+ if (event.keyCode === Event.KEY_RETURN) {
274
+ event.stop();
275
+ return false;
276
+ } else { return true; }
277
+ });
278
+
279
+ })();
280
+
281
+
282
+
283
+
284
+
285
+ // function dyliChange(dyli, id) {
286
+ // var dyli_hf =$(dyli);
287
+ // var dyli_tf =$(dyli+'_tf');
288
+
289
+ // return new Ajax.Request(dyli_hf.getAttribute('href'), {
290
+ // method: 'get',
291
+ // parameters: {id: id},
292
+ // onSuccess: function(response) {
293
+ // var obj = response.responseJSON;
294
+ // if (obj!== null) {
295
+ // dyli_hf.value = obj.hf_value;
296
+ // dyli_tf.value = obj.tf_value;
297
+ // dyli_tf.size = (dyli_tf.value.length > 64 ? 64 : dyli_tf.value.length);
298
+ // }
299
+ // }
300
+ // });
301
+ // }
302
+
303
+
304
+ // function refreshList(select, request, source_url) {
305
+ // return new Ajax.Request(source_url, {
306
+ // method: 'get',
307
+ // parameters: {selected: request.responseJSON.id},
308
+ // onSuccess: function(response) {
309
+ // var list = $(select);
310
+ // list.update(response.responseText);
311
+ // }
312
+ // });
313
+ // }
314
+
315
+ // function refreshAutoList(dyli, request) {
316
+ // return dyliChange(dyli, request.responseJSON.id);
317
+ // }
318
+
319
+
320
+ // (function() {
321
+
322
+ // document.on("click", "a[data-new-item]", function(event, element) {
323
+ // var list_id = element.readAttribute('data-new-item');
324
+ // var url = element.readAttribute('href');
325
+ // openDialog(url, list_id);
326
+ // event.stop();
327
+ // });
328
+
329
+
330
+ // document.on("click", "a[data-dialog-open]", function(event, element) {
331
+ // var url = element.readAttribute('data-dialog-open');
332
+ // if (url === 'true') {
333
+ // url = element.readAttribute('href');
334
+ // }
335
+ // openDialog(url, element.readAttribute('data-dialog-update'));
336
+ // event.stop();
337
+ // });
338
+
339
+ // document.on("click", "a[data-dialog-close]", function(event, element) {
340
+ // var dialog_id = element.readAttribute('data-dialog-close');
341
+ // closeDialog(dialog_id);
342
+ // event.stop();
343
+ // });
344
+
345
+ // document.on("submit", "form[data-dialog]", function(event, form) {
346
+ // var dialog_id = form.readAttribute('data-dialog');
347
+ // var dialog = $(dialog_id);
348
+
349
+ // var field = new Element('input', { type: 'hidden', name: 'dialog', value: dialog_id });
350
+ // form.insert(field);
351
+
352
+ // new Ajax.Request(form.readAttribute('action'), {
353
+ // method: form.readAttribute('method') || 'post',
354
+ // parameters: Form.serialize(form),
355
+ // asynchronous: true,
356
+ // evalScripts: true,
357
+ // onLoaded: function(request){ resizeDialog(dialog_id); },
358
+ // onSuccess: function(request){
359
+ // if (request.responseJSON === null) {
360
+ // // No return => validation error
361
+ // dialog.update(request.responseText).resize();
362
+ // } else {
363
+ // // Refresh list or execute call
364
+ // var updated_id = dialog.readAttribute('data-dialog-update');
365
+ // var updated = $(updated_id);
366
+ // if (updated !== null) {
367
+ // if (updated.readAttribute('text_field_id') === null) {
368
+ // var url = updated.readAttribute('data-refresh');
369
+ // var parameter = updated.readAttribute('data-id-parameter-name');
370
+ // if (parameter === null) {
371
+ // parameter = 'selected';
372
+ // }
373
+ // var parameters = $H();
374
+ // parameters.set(parameter, request.responseJSON.id);
375
+ // if (url !== null) {
376
+ // new Ajax.Updater(updated_id, url, {
377
+ // method: 'GET',
378
+ // asynchronous:true,
379
+ // evalScripts:true,
380
+ // parameters: parameters,
381
+ // onSuccess: function(request) { form.fire("layout:resize", request); }
382
+ // });
383
+ // }
384
+ // } else {
385
+ // dyliChange(updated_id, request.responseJSON.id);
386
+ // }
387
+ // }
388
+ // // Close dialog
389
+ // closeDialog(dialog_id);
390
+ // }
391
+ // }
392
+ // });
393
+ // event.stop();
394
+ // return false;
395
+ // });
396
+
397
+
398
+
399
+ // })();
data/formize.gemspec ADDED
@@ -0,0 +1,64 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{formize}
8
+ s.version = "0.0.2"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = [%q{Brice Texier}]
12
+ s.date = %q{2011-08-12}
13
+ s.description = %q{Like simple_form or formtastic, it aims to handle easily forms but taking in account AJAX and HTML5 on depending fields mainly.}
14
+ s.email = %q{brice.texier@ekylibre.org}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ "LICENSE.txt",
22
+ "README.rdoc",
23
+ "Rakefile",
24
+ "VERSION",
25
+ "assets/javascripts/formize.js",
26
+ "formize.gemspec",
27
+ "lib/formize.rb",
28
+ "lib/formize/action_pack.rb",
29
+ "lib/formize/definition.rb",
30
+ "lib/formize/definition/element.rb",
31
+ "lib/formize/definition/field.rb",
32
+ "lib/formize/definition/field_set.rb",
33
+ "lib/formize/definition/form.rb",
34
+ "lib/formize/definition/form_element.rb",
35
+ "lib/formize/form_helper.rb",
36
+ "lib/formize/generator.rb",
37
+ "test/helper.rb",
38
+ "test/test_formize.rb"
39
+ ]
40
+ s.homepage = %q{http://github.com/burisu/formize}
41
+ s.licenses = [%q{MIT}]
42
+ s.require_paths = [%q{lib}]
43
+ s.rubygems_version = %q{1.8.7}
44
+ s.summary = %q{Simple form DSL with dynamic interactions for Rails}
45
+
46
+ if s.respond_to? :specification_version then
47
+ s.specification_version = 3
48
+
49
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
50
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
51
+ s.add_development_dependency(%q<rcov>, [">= 0"])
52
+ s.add_development_dependency(%q<actionpack>, [">= 0"])
53
+ else
54
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
55
+ s.add_dependency(%q<rcov>, [">= 0"])
56
+ s.add_dependency(%q<actionpack>, [">= 0"])
57
+ end
58
+ else
59
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
60
+ s.add_dependency(%q<rcov>, [">= 0"])
61
+ s.add_dependency(%q<actionpack>, [">= 0"])
62
+ end
63
+ end
64
+
@@ -0,0 +1,63 @@
1
+ module Formize
2
+
3
+ module ActionController
4
+
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+
11
+ # Generates controller and view method working together
12
+ # This methods allows to develop dynamic forms without using partials
13
+ # and another action, only formize or formize_*.
14
+ def formize(*args, &block)
15
+ name, options = nil, {}
16
+ name = args[0] if args[0].is_a? Symbol
17
+ options = args[-1] if args[-1].is_a? Hash
18
+ name ||= self.controller_name.to_sym
19
+ model = (options[:model]||name).to_s.classify.constantize
20
+ options[:controller_method_name] = "formize#{'_'+name.to_s if name != self.controller_name.to_sym}"
21
+ options[:view_form_method_name] = "_#{self.controller_name}_formize_form_#{name}_tag"
22
+ options[:view_fields_method_name] = "_#{self.controller_name}_formize_fields_#{name}_tag"
23
+ options[:method_name] = options[:view_fields_method_name]
24
+ form = Formize::Form.new(name, model, options)
25
+ if block_given?
26
+ yield form
27
+ else
28
+ formize_by_default(form)
29
+ end
30
+ generator = Formize::Generator.new(form, self)
31
+ class_eval(generator.controller_code, "#{__FILE__}:#{__LINE__}")
32
+ ActionView::Base.send(:class_eval, generator.view_code, "#{__FILE__}:#{__LINE__}")
33
+ end
34
+
35
+ private
36
+
37
+ # Generates list of usable field
38
+ def formize_by_default(form)
39
+ form.field_set do |f|
40
+ for column in model.columns
41
+ next if column.name =~ /_count$/
42
+ if column.name =~ /_id$/
43
+ reflections = model.reflection.select{|x| x.primary_key_name.to_s == column.name.to_s }
44
+ if reflections.size == 1
45
+ f.field(column.name.gsub(/_id$/, ''))
46
+ # elsif reflections.size > 1 # AMBIGUITY
47
+ # elsif reflections.size < 1 # NOTHING
48
+ end
49
+ else
50
+ f.field(column.name)
51
+ end
52
+ end
53
+ end
54
+ return form
55
+ end
56
+
57
+ end
58
+
59
+ end
60
+
61
+ end
62
+
63
+ ActionController::Base.send(:include, Formize::ActionController)