The changes made to my form_assistant plugin warrant a new post. They’re somewhat drastic when compared to how it worked originally.
General Usage
To use the form_assistant randomly in your application, take this approach:
1 2 3 | <% form_assistant_for @project do |form| %> // typical form_for stuff <% end %> |
That’s the only thing you need to know. There’s no longer a separate helper for the inline errors, since the new version uses templates now.
If you’d like to make it the default in your application, take this approach:
1 | ActionView::Base.default_form_builder = RPH::FormAssistant::FormBuilder |
That would allow you to use form_for as you normally would.
Templates
The most notable change (I think) is the use of templates. Now, each rendered element has a corresponding template. The naming (by default) is the name of the helper. For example:
1 2 3 4 5 | # renders app/views/forms/_text_field.html.erb <%= form.text_field :name %> # renders app/views/forms/_text_area.html.erb <%= form.text_area :description %> |
And so on. Of course, you can override the template for those special cases by passing a :template option.
1 2 | # renders app/views/forms/_custom_template.html.erb <%= form.text_field :name, :template => 'custom_template' %> |
This is great because you can keep all of your form presentation in one area. It keeps them DRY.
It’s worth noting the variables that are automatically made available to each template (see line 90 of form_assistant.rb).
1 2 3 4 5 6 7 8 |
locals = {
:element => element,
:label => label,
:errors => errors,
:tip => tip,
:helper => helper,
:required => required
}
|
To get started with basic templates, run this command from your project root:
1 | $ rake form_assistant:install |
That will create a /forms directory under app/views and put some default forms in there. Modify them at your own will (it’s recommended, actually).
Labels
Labeling form fields is a tedious task, but it’s important, too. Here’s how you can work with labels using the form_assistant:
1 2 3 4 5 6 |
<%= form.text_field :title, :label => 'Project Title' %>
<%= form.text_field :title, :label_text => 'Project Title' %>
<%= form.text_field :title, :label_class => 'required' %>
<%= form.text_field :title, :label_id => 'dom_id' %>
<%= form.text_field :title, :label => { :text => 'Project Title', :id => 'dom_id', :class => 'required' } %>
<%= form.text_field :title, :label => false %>
|
If you don’t do anything, the label will be a humanized version of the field name by default.
Defaults and Configuration
There are a few things you can customize that will change the way the form_assistant behaves, globally.
1 2 3 4 5 6 | # config/initializers/form_assistant.rb RPH::FormAssistant::FormBuilder.ignore_templates = true # defaults to false RPH::FormAssistant::FormBuilder.ignore_labels = true # defaults to false RPH::FormAssistant::FormBuilder.ignore_errors = true # defaults to false RPH::FormAssistant::FormBuilder.template_root = '...' # defaults to app/views/forms |
Examples and Bonus Features
Using fields_for alone won’t automatically give you form_assistant niceties. You must call it in the context of the form object, and then it will work as expected.
1 2 3 4 5 |
<% form_assistant_for @project do |form| %>
<% form.fields_for :tasks do |task_fields| %>
<%= task_fields.text_field :name %>
<% end %>
<% end %>
|
You can set a required flag (maybe used for a CSS class or a ”*” or something) by simply passing it:
1 | <%= form.text_field :title, :required => true %> |
There are a few other things, such as easy cancel links:
1 2 3 4 5 6 7 8 9 10 |
<%= form.cancel %>
<span class="cancel">
<a href="/wherever/the/user/came/from">Cancel</a>
</span>
# other options:
<%= form.cancel 'Go Back' %>
<%= form.cancel 'Nevermind', :path => some_path %>
<%= form.cancel 'Go Back', :attrs => { :class => 'go-back' } %>
|
See for yourself how easy it is to add your own custom helpers to form_assistant.
Also, make sure you’re aware of partial and fieldset, too, as they’re extremely useful (thanks, Chris).
See the Docs
It’s seriously advised that you go through the README, as I haven’t quite covered everything in this post. It (the README) will serve as the most up-to-date documentation for the time being.
Conclusion
Hopefully this post will take the place of the out-dated one, and assist any confusion thereof. I personally think forms are the most tedious thing to deal with in a Rails application, and this plugin has severely improved my code.
If you don’t want to use my plugin, you should at least explore the options for creating your own—it’s worth the time and the effort, I promise.
As expected, you can find it on GitHub. Enjoy.

01
Danny on Wed Mar 11 at 08:23AM
Hi!
Great update.
I do have one suggestion:
It is possible to set an empty error on an activerecord field like this:
@user.errors.add(:email, "")
I want to do this because for example if the login fails i give an error on base instead of a specific field.
I do set the empty errors so the fields get market as error.
Now in your has_errors? method you check if a field has errors by calling object.errors[field].blank?
I suggest you change this to object.errors[field].nil? so you support empty errors.
Then i can do something like this in my template:
Thanks
02
Zac Zheng on Thu Dec 17 at 11:40AM
I use your plugin regularly and love it for its utility.
I sometimes come to a situation where the whole form is using assitant_form but I would like some fields NOT to be. This happens when I need more control.
I am having difficulty achieving this. I have tried this for fields that should not use assistant_form:
- f.fields_for :web_page, @web_page, :builder => ActionView::Base.default_form_builder do |ff|
…
or :builder => nil
But neither works and I’ stumped. Can you offer any advice on this?
03
Ryan on Thu Dec 17 at 02:55PM
@Zac Zheng -
Yes, there is a way around this. Try passing
template => false.Let me know if that didn’t fix your problem.
As for the
fields_forsituation, you could try neglecting the form object (fin your case). Something like:I think that would revert back to its normal behavior, as the form assistant builder lies in the form object, so if you don’t use it,
fields_foris none the wiser.04
Paul on Mon Jan 25 at 01:21PM
Quick q:
Can I add a spinner? I’m using form_assistant to upload large files. Currently, I don’t have anything to show the user that the request is still in process.
Thanks!
05
Ryan on Mon Jan 25 at 01:37PM
@Paul -
That should actually be something that is handled via javascript. If you’re using jQuery, you could do something like this:
$('input[type=submit]').click(function() { $(this).val('Working...') })That would change the button to say “Working…” when it is clicked. Or, if you’re using Ajax and looking for something more universal, like a loading graphic, you could do something like this:
$.ajaxSetup({ 'beforeSend': function(xhr) { $('#loading').show() }, 'complete': function(xhr) { $('#loading').hide() } })That would show an element with a DOM id of ‘loading’ anytime an Ajax request was performed – so you could put whatever you wanted in there, a message, a spinner, etc. You could also set it up with
content_forif you wanted custom loading messages per view.Let me know if you need further help with your spinner issue, but I’m sorry to say that it’s not something that form_assistant should be concerned with.
Thanks!
06
Paul on Tue Jan 26 at 10:58AM
Thanks for the response. I’ll dig into this later today and let you know how it goes.