HTML_QuickForm in …. Rails ?
Caution Thinking Out Aloud:
Okay the purists have just decided to kill me. Let the religious wars begin !
No seriously, everytime I do some coding in an old PHP app which is heavily dependent on HTML_QuickForm, I keep questioning how possible would it be to convert it across to Rails, and whether any other persons like myself would think all of their Christmases have come at once. Here’s my hopefully rational thought processes behind this. Rails is a fantastic CRUD machine. If you want to build single model forms with validations in them, absolutely beautiful. Nothing could feel more clean and make you as a developer go ‘thats sweet’. Fantastic.
Now try and do a model-less form, with validations, or combine multiple models within one form. Things like the presenter pattern get bandied about. Real world case example - a form to choose options for defining a report. Nothing that you want to put in a model as it’s not a represenation of a ‘thing’ (although some may argue it is).
I wonder and am sitting on the fence of, whether to try implementing quickform for rails. For those that haven’t been exposed to it, in a nutshell it’s a brilliant little php library that lets you create a representation of a form, with rules, pass the form into a renderer which dumps out the html on a page, but that’s not all, it assists you in processing the form on submission. So some code can look like this (not syntactically correct, but close enough), which does all of the hard work of writing out html, setting up client side js, and server side processing.
//page myform.php $myform = new HtmlQuickForm('form_name', 'myform.php'); $abc = $myform->addElement('text', 'product_name', 'Product Name:'); $myform->addRule('product_name', 'required', 'You must enter a product name'); if ($myform->validate()) { //process form var_dump( $abc->getValue() ); } else { //setup form $abc->setValue('123') } // then in any template which dumps out the rails code $myForm->display();
It doesn’t seem like much, but put half a dozen or more options on the form, different processing rules, and suddenly it’s done a lot of the heavy lifting for you.
What would it take to add this to Rails ? How would (I personally) fit it in. It doesn’t really sit within either the model, view, or controller. The view should render the output, it doesn’t really fit within a model as it’s not a representation of a thing. It most closely sits in the controller, but you don’t really want to clutter the controller with your form models.
Here’s some thoughts
An initial idea, with everything defined in the controller, then dumped into the view by a @my_form.output
class FormController < Application def do_form get_form if @myForm.posted #do stuff else #populate stuff end end protected def create_report @myform = RFormBuilder.new do |f| f.call_back_url = { :controller => 'form', :action => 'do_form' } f.name = 'myform' end @myform.add_text( :name => 'product_name', :label => 'Product Name', :rule => { :required => :true, :msg => 'You must add this' } ) end end
OR
Maybe we add in a new folder in the main app
/app/
/controllers
/models
/views
/forms
myform.rb
And the treat myform.rb kinda like a model, but kinda not.
class MyForm < RFormBuilder defaults :name => 'my_form', :call_back_url => '/myform' text_field :name => 'product_name', :label => 'Product Name', :required => :true #gets called when form is posted def validate return true if field_product_type == 'abc' end end # now in FormController def do_form get_form @my_form = MyForm.new if @myForm.valid #do stuff render :text => @my_form.field_product_name else #populate stuff end end
What do you think ? Am I stark raving mad. Could this just work ? I think so and am willing to take up the challenge…
Rowan

11 Comments, Comment or Ping
Fabien
Having worked with HTML_Quickform extensively in the past, I decided to create something similar (and hopefully even more elegant) in Ruby.
It’s called ActiveForm, and you can find it at RubyForge: http://activeform.rubyforge.org/ - as far as I can see, it does exactly like you describe. Feel free to contact me if you need further information.
Nov 28th, 2007
admin
Fabien - that’s pretty much on the money. Good to know I’m not the only one on that same thought train - going to try out ActiveForm, likely today and let you know how it works out. Thank you !!!!!
Nov 28th, 2007
Brent
another simpler option (oddly enough called ActiveForm as well)
http://snippets.dzone.com/posts/show/1963
This probably does not address all the things you are interested in, but may be a bit more attractive to a Rails “purist”
Nov 28th, 2007
Fabien
Hi Rowan, to get started try some of the examples on Rubyforge - you can find the source with the plugin as well. Although there doesn’t seem too much documentation, most is captured in the extensive unit tests included. Some things you might like from a Ruby standpoint is that each element behaves like an Enumerable and you can use bracket syntax to access elements. By default elements are rendered using Builder for markup. There’s nothing stopping you from outputting individual elements or groups/sections inside an ERB template (or anywhere else), since elements respond to render on their own (with to_s for convience).
Brent, the snippet you give is indeed very simple and in my opinion kind of a hack, since you’d like AR validations but get a ton of unused features with it. I dare to say, makes it less attractive to a Ruby “purist”. If you’d like proper validation mixins, use Validatable (http://validatable.rubyforge.org/) with your non AR models.
Nov 29th, 2007
admin
Thanks Fabien, I’ve been wading through unit tests yesterday - I needed to dynamically add elements to the form, after it’s been built. Figured out how to do that but not getting quite what I expect on export_values. However it’s off to a *very* promising start. Some more work today should nail it down. I’ll write up some further examples for people as I go through this which I’ll blog and you can put up on your rubyforge site.
Nov 29th, 2007
Fabien
Hi Rowan, I’m glad you like it. As for adding elements dynamically, in good Ruby spirit, the ‘glue’ never sets, so it should definately be possible. Maybe the nested values of export_values aren’t what you expected? Send me an email if you’d like me to have a look. Also, I’m really looking forward to any blogposts - I didn’t find a spare moment yet to maintain a blog of my own. A shame, I know!
Nov 29th, 2007
Brent
Fabien… thanks for that link. That _is_ a “purer” way to deal with it.
(nice work on your much more dynamic - and flexible - solution by the way)
Cheers.
Nov 30th, 2007
admin
Fabien - many thanks for your comments - sending you an email.
Nov 30th, 2007
Fabien
Rowan - did you recieve my reply? Also, is it working for you now?
Dec 5th, 2007
Ashley Coker
How do you add elements dynamically to the form after it is built. I am trying to add a number of previous addresses to a form, but I don’t know how many addresses a person may have and hence need a dynamic way of adding them as form elements.
Any ideas or solutions much appreciated.
Feb 28th, 2008
admin
Ashley - if you look in the test folder of the plugin you’ll find a bunch of tests that show you how to do this stuff, I just had a play and here’s an option for you …
@form = build_active_form :report_filter, :filter
#make a new element
@form.define_element_at_bottom(:text, :my_custom_element)
#must add this to get the value back out
@form.update_from_params(params)
if @form.submitted? && @form.validated?
@export_output = @form.export_values
end
Feb 28th, 2008
Reply to “HTML_QuickForm in …. Rails ?”