form_assistant plugin updates
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.

Danny Wednesday, 11 Mar, 2009 Posted 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
Zac Zheng Thursday, 17 Dec, 2009 Posted 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?
Ryan Thursday, 17 Dec, 2009 Posted 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.Paul Monday, 25 Jan, 2010 Posted 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!
Ryan Monday, 25 Jan, 2010 Posted 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!
Paul Tuesday, 26 Jan, 2010 Posted at 10:58AM
Thanks for the response. I’ll dig into this later today and let you know how it goes.
Nik Wednesday, 02 Jun, 2010 Posted at 06:48PM
I have been reading about your plugin and I am really happy with it. But your documentation talks about a form.submission and a form.cancel
I cannot get either one to work, it appears they have been removed. If so why? It would be extremely useful to me to be able to write form.submit or form.submission and have my submit button embedded in a template too.
How would I achieve that?
Ryan Wednesday, 02 Jun, 2010 Posted at 10:07PM
Nik -
I’m sorry about that, this post is rather out-of-date. Those two methods (
form.submission()andform.cancel()) no longer exist. The reason is because those “helpers” aren’t really what the form_assistant is about. Its main concern is creating form fields, and I got a little carried away building features that were out of scope. So I yanked them out (actually, Chris did). You can find accurate documentation from the README.However, that doesn’t help you solve your problem. If you’re really ambitious, you can checkout the commit that removed all of that stuff and add it back in. But specifically, here’s an example for how you might just add in the
cancel()helper:If you stick that in the
publicsection of form_assistant.rb, it should be available in your form-assisted forms. But if you get into adding a bunch of helpers, you should probably stick them in a separate module and include it in (like I did before). That’s a bit cleaner, and then if/when you realize those don’t belong in the plugin, it’s easy to pull out :-)Let me know if you have any other questions. Hope that helps.
Nik Thursday, 03 Jun, 2010 Posted at 10:55AM
Thanks Ryan, That will get me started on what I want to achieve. I would agree that the ‘cancel’ piece should be in a different plugin. However, having the ability to put the submit button in a template would be a really good addition to this plugin. Maybe I will make a fork of this with the submit template added in.
This is what I would like to do:
Would output something like this: (based on my customized templates)
Notice the submit button is placed inside a div which would be the template that I had specified for it. This would allow me to float the divs containing the form elements if I chose to.
Anyway, I will checkout the source and see if I can add this functionality. Let me know what you think.
Thanks again
Ryan Thursday, 03 Jun, 2010 Posted at 02:16PM
I do understand your desire for that. I do something similar on all of my forms. Here’s what I currently do (in application_helper.rb):
That allows me to do things like:
Or if you wanted to pass options to the submission wrapper, something like:
Just an option.
In your example, though, you’re wanting the
form.submitto be a native feature if the form assistant plugin. The way the form_assistant works is it overrides all of Rails’ form helpers and redefines them to use the templates. So if you want thesubmitto be a part of that list, it’s pretty simple. Just add it to the list of form helpers, like so (look for ‘submit’ at the end of the line):And then in your app/views/forms/ directory, just add a
_submit.html.erbtemplate and the field will automatically use that template any time you’re callingform.submit. And in there, you can then wrap your submit in any div you want, along with a cancel link. Look at the other form templates to see all of the things that are made available – you’ll mostly be concerned with theelementvariable, though (that’s the actual HTML item).Just to be clear, your
_submit.html.erbtemplate might look like this:Hopefully that makes sense. Let me know if you run into trouble. I had the
submithelper in the list of fields at some point, but I took it out. I’m having a hard time remembering why, though :-)Nik Thursday, 03 Jun, 2010 Posted at 04:22PM
That is exactly what I ended up doing, thanks for your replies.
It took me a little bit to figure out that ‘submit’ was not part of
ActionView::Helpers::FormBuilder.field_helpersthough.It is working exactly as I expected now. Thank you.
BTW, This plugin is very useful. ;-)