Form Creation Techniques

Hi All,

I’ve been playing with ruby for some time now, but mostly with Models
and Controllers. I’m now to the point where I’d like to start working an
the View part of MCV more. My problem is I’m having a very difficult
time understanding how to work with forms.

What are some good (preferably on-line) references for making useful
forms with the Rails framework?

I have two main issues:

  • Creating and handling forms that do not directly correspond to the
    fields in a Model class
  • Dynamically generating forms at run-time based on the a polymorphic
    association.

What I would really like (and have tried to write without any success)
is a way of specifying what data I need from the user and having the
program write a form to get and validate that data. If there is such a
thing I’d like to know about it. (is this what XForms are?)

John M.

First I want to point you to the reference or documentation page where
you can find many answers to many questions :smiley:

Official: (no beauty)
http://api.rubyonrails.org/

Ajax: (more beauty)
http://www.railsbrain.com/api/rails-1.2.3/doc/index.html

John M. wrote:

I have two main issues:

  • Creating and handling forms that do not directly correspond to the
    fields in a Model class

Well, you can do that easily :slight_smile:

You can use the form fields like this (depend on how you created them)
params[:field]
or
params[:name][:field]

  • Dynamically generating forms at run-time based on the a polymorphic
    association.

This would be cool, but I don’t know how :smiley:

What I would really like (and have tried to write without any success)
is a way of specifying what data I need from the user and having the
program write a form to get and validate that data. If there is such a
thing I’d like to know about it. (is this what XForms are?)

Well, you could in your controller create array with the information you
want to retrieve and which type, then you can use that array to create
the form :slight_smile:

I hope that helped a little bit :smiley:

Thanks to Jamal S. for the reply!

I have read the API docs, and I must admit they have a lot of detail,
but not much on best practices and almost nothing on integrating the
helper functions into a good looking and functional web page. It is
also not clear how best to add JavaScript functionality to the elements.

There have been several excellent blog posts and wiki pages about
designing useful Models and RESTful controllers, but there seems to be
very little about how to create DRY and elegant view code, particularly
where custom forms are concerned.

Re: dynamically generating forms, I have written a class (Inherits from
Hash actually) that I could use to describe form data, but I’ve gotten
stuck trying use this data to build a form, and decided that there must
be someone who had done a better job. Part of my reason for posting was
in hope of finding a replacement. Again, I keep running into XForms
when I look, but I’m not sure what they are or how they work.

Any additional help or references would be great.

Thanks,

John M.

Jamal S. wrote:

First I want to point you to the reference or documentation page where
you can find many answers to many questions :smiley:

Official: (no beauty)
http://api.rubyonrails.org/

Ajax: (more beauty)
http://www.railsbrain.com/api/rails-1.2.3/doc/index.html

John M. wrote:

I have two main issues:

  • Creating and handling forms that do not directly correspond to the
    fields in a Model class

Well, you can do that easily :slight_smile:

You can use the form fields like this (depend on how you created them)
params[:field]
or
params[:name][:field]

  • Dynamically generating forms at run-time based on the a polymorphic
    association.

This would be cool, but I don’t know how :smiley:

What I would really like (and have tried to write without any success)
is a way of specifying what data I need from the user and having the
program write a form to get and validate that data. If there is such a
thing I’d like to know about it. (is this what XForms are?)

Well, you could in your controller create array with the information you
want to retrieve and which type, then you can use that array to create
the form :slight_smile:

I hope that helped a little bit :smiley:

Ed Howland wrote:

On 8/22/07, John M. [email protected] wrote:

There have been several excellent blog posts and wiki pages about
designing useful Models and RESTful controllers, but there seems to be
very little about how to create DRY and elegant view code, particularly
where custom forms are concerned.

By this do you mean non-model based forms?

For all intents and purposes yes. I have a Building model that holds
many different types of buildings (warehouse, retail, office, condo,
apartment, etc…) The table needed to hold all the different aspects was
large and sparsly populated so I decided that I would take all fields
not common to all buildings and marshal them to a column named ‘data.’
But now I want to edit that information from a web page. The business
rules I’m working with mean that every building needs a to work with
slightly different set of information. I need to be able to build a
form based on what information the user is allowed to change and it will
be different for every instance of Building.

For model based forms, and model-combos, you should look into form_for
and fields_for helper methods. These allow you to use a block to
describe your form and expand out the various field level helpers
(which sets the field names automatically from the model.)

ActionView::Helpers::FormHelper

I have used this almost exclusively to do forms up to this point. It’s
great, it just works. (except that it cannot pre-validate the forms with
JavaScript before hitting the server)

I have attempted to use the FormTagHelper classes, but they seem rather
messy, and require that I put too much logic into the view for my taste.
My biggest problem here is that I’m not a web design expert (I’m a real
programmer :wink: and I cannot find any good references either on form
design or the “opinions” that rails uses to construct forms from it’s
Helper functions.

For example there is a sublease checkbox for some buildings when it’s
checked I need to collect some information about the terms for of the
sublease. I need more information for buildings built after 1987 and
extra information for some states. I would like design a form that adds
only the extra needed fields to the page once the box is checked. At
the moment I am displaying fields for every conceivable situation and
having to validate the result once it gets back to the server. Needless
to say this will not work in a live environment, we’ll have someone
spending all day trying to find the non-existent California Earthquake
Retrofit report for a brand-new warehouse in Maine.

Re: dynamically generating forms, I have written a class (Inherits from
Hash actually) that I could use to describe form data, but I’ve gotten
stuck trying use this data to build a form, and decided that there must
be someone who had done a better job. Part of my reason for posting was
in hope of finding a replacement. Again, I keep running into XForms
when I look, but I’m not sure what they are or how they work.

You should look into subclassing FormBuilder that you can use with
form_for in your views.

The best reference/guide for this is the Agile Web D. With
Rails, 2E IMO.

I have the first ed and my perusal in my perusal of the second, I didn’t
find much that I could not have already learned from the docs. How
would I subclass FormBuilder in the example above?

HTH,
Ed

Thanks,

John M.

For automatic building of forms i did something like this:

<% @columns.each do |column, title| -%> <%= title -%>: <%= auto_form_method f, @resource, column, auto_rest_data -%> <% end -%>

and @columns should be populated like this in the controller:

@columns= [[:attribute1, ‘title1’],
[:attribute2, ‘title2’]] # …etc…

@foreign_keys= { :other_model_id => OtherModel }

auto_form_method is a method helper:

# Standard selection of field type given the column type.
def auto_form_method form, resource, attribute, auto_rest_data

  # Check if attribute is indeed a model relation foreign key
  if @foreign_keys.include? attribute
    model= @foreign_keys[attribute]
    auto_model_foreign_key_select form, resource, model, attribute
  else
    auto_standard_form_method form, resource, attribute
  end
end

# Creation of a select tag given a foreign key
def auto_model_foreign_key_select form, resource, model, attribute

  option_tags= options_from_collection_for_select model.find(:all),
                   'id', 

‘label’,
h(resource.send(attribute))

  select_tag "resource[#{attribute}]", option_tags, options
end

# This Helper returns the apropiate form method
# for the resource and attribute
# TODO: This is pretty ugly :) ...
# Is there any other way to acomplish this functionality?
def auto_standard_form_method form, resource, attribute
  case resource.column_for_attribute(attribute).type
  when :string      : form.text_field(attribute)
  when :text        : form.text_area(attribute)
  when :integer     : form.text_field(attribute)
  when :float       : form.text_field(attribute)
  when :decimal     : form.text_field(attribute)
  when :datetime    : form.text_field(attribute)
  when :timestamp   : form.text_field(attribute)
  when :time        : form.text_field(attribute)
  when :date        : form.text_field(attribute)
  when :binary      : form.check_box(attribute)
  when :boolean     : form.check_box(attribute)
  end
end

Summary: It is not automatic nor easy to acomplish, IMO!!!

EmmanuelOga.blogspot.com

On 8/22/07, John M. [email protected] wrote:

There have been several excellent blog posts and wiki pages about
designing useful Models and RESTful controllers, but there seems to be
very little about how to create DRY and elegant view code, particularly
where custom forms are concerned.

By this do you mean non-model based forms?

For model based forms, and model-combos, you should look into form_for
and fields_for helper methods. These allow you to use a block to
describe your form and expand out the various field level helpers
(which sets the field names automatically from the model.)

Re: dynamically generating forms, I have written a class (Inherits from
Hash actually) that I could use to describe form data, but I’ve gotten
stuck trying use this data to build a form, and decided that there must
be someone who had done a better job. Part of my reason for posting was
in hope of finding a replacement. Again, I keep running into XForms
when I look, but I’m not sure what they are or how they work.

You should look into subclassing FormBuilder that you can use with
form_for in your views.

The best reference/guide for this is the Agile Web D. With
Rails, 2E IMO.

HTH,
Ed

Ed Howland

“The information transmitted is intended only for the person or entity
to which it is addressed and may contain proprietary, confidential
and/or legally privileged material. Any review, retransmission,
dissemination or other use of, or taking of any action in reliance
upon, this information by persons or entities other than the intended
recipient is prohibited. If you received this in error, please contact
the sender and delete the material from all computers.”