views:

630

answers:

1

I am looking for an example of how to create a custom form builder for a radio button list bound to an object that acts_as_tree. I already have the code that displays the radio button list but want to DRY it up by refactoring into a formbuilder. I can't find any examples of a custom form builder for radio button lists.

Any pointers/links would be appreciated.

A: 

Assuming you're calling form_for on this model often from many different views and every form is going to have the same set of radio buttons. There are a few routes you can take here. However, I can't tell if you're asking how to automatically add the radio button list or just condense it.

Adding the radio button list automatically requires a little more knowledge of the ActionView internals than I can share. Essentially you'll want to figure out how things are rendered and override the fields_for method in ActionView::Helpers::FormHelper to work just right. Unfortunately FormBuilders don't work that way. So it's going to be a lot more trouble than it's worth.

A better approach is to create a method that generates all your radio buttons in your custom form builder. To keep things simple in the event of a change, we're going to add a constant to the model. I've arbitrarily decided it will be a hash where each key is an attribute method you want to represent with a radio button list in forms, and each value is a list of acceptable values for that attribute. This makes it simple to generate multiple lists of radio buttons without having to change the form builder. P.S. You can also use the hash to validate the contents of any attribute associated with radio buttons.

/app/models/example.rb

class Example < ActiveRecord::Base
  ...
  RADIO_BUTTON_HASH = {
    :attribute_a => [:accepted_value_a1, :accepted_value_a2, :accepted_value_a3],
    :attribute_b => [:accepted_value_b1, :accepted_value_b2],
    ...
  }


   def self.radio_buttons_sort(a,b)
     # sort method to ensure that multiple radio buttons lists appear in the order you want
   end

   def self.radio_buttons_sorted
     RADIO_BUTTON_HASH.sort{|a,b| radio_button_sort(a,b)}
   end
   ...
end

I added a couple of convenience methods in addition to the hash, they're not necessary but they provide a cleaner method of standardizing output.

**/app/helpers/example_helper.rb module ExampleHelper

  # the custom FormBuilder
  class ExampleFormBuilder < ActionView::Helpers::FormBuilder    

    # add onkeypress and set maxlength of field to 3 to all text fields
    def radio_button_list(options={})
      Example.sorted_radio_buttons.each do |method,values|
        values.each do |value|
          radio_button(method, value, options)
        end
      end
    end

  end
end

Then from a view where ExampleHelper is included (done by default in any view rendered by the Example controller).

<%form_for @example, :builder => ExampleFormBuilder do |f| %>
  ...

  <%=f.radio_button_list %>
<%end%>
EmFi
Thanks for your reply. I spent a few hours trying to work it out last night by going through the rails helpers and eventually came a similar solution.
Damian
Yeah, the official documentation isn't very helpful on this subject. The short version is you use custom FormBuilders to override FormHelper methods with your options, or create new helper methods.
EmFi