Technical
Form Helpers

KISS – or no need to play a ‘Shtirlitz’ on Rails


<%= select(:client,:frequency,%w{ Daily Weekly Monthly Yearly }) %>

submit_tag_with_conformation herlper


#TEST FIRST
  def test_submit_tag_with_conformation
    with_are_you_sure = %(<input name=\"commit\" onclick=\"if (!confirm('Are You Sure')) return false; this.form.submit()\" style=\"font-size:10px\" type=\"submit\" value=\"Add\" />)
    with_id = %(<input id=\"test\" name=\"commit\" onclick=\"if (!confirm('Are You Sure')) return false; this.form.submit()\" type=\"submit\" value=\"Delete\" />)

    assert_equal with_are_you_sure,submit_tag_with_conformation("Add","Are You Sure",{:style => "font-size:10px"})
    assert_equal with_id,submit_tag_with_conformation("Delete","Are You Sure",{:id => "test"})
  end
#CODE
  def submit_tag_with_conformation(name,message,html_options={})
    tag :input,{"type" => "submit",
                "name" => "commit",
                "value" => name,
                "onclick" => "if (!confirm('"+message.to_s+"')) return false; this.form.submit()"}.update(html_options.stringify_keys)
  end

Meta-Data Driven Select

Ones I had a case where users would use override for certain column. So that the scenario would be:
  1. Select Certain Field ( drop down box)
  2. Set the value for that field to be changed if approved.

Rather then creating an array of fields that will be changed later, I used meta-data to drive the drop down box.


<%= select(:some_table,
           :field,
           SomeTable.column_names.map{|field| [field,field]) %>

So this way if the field has been changed, even in production environment
user will see a change in the drop down immediately.

Select tag with blank for the first option

This select will output column names for the Security2Risk table, including blank in front so that on change would fire up and disable fields base on logic in disable_column_for_field method


<select name='Sec2Override[field]' id="fields" 
        onchange="<%= remote_function :url => {:action => "disable_column_for_field"}                    
                                               :with => "'field_name='+$(fields).value" %>">
<% for attr in [""].concat( Security2Risk.column_names.sort) %>
  <option value=<%= attr%> <% if attr == @Sec2Override.field %> selected="selected" <% end %>><%= attr %></option>
<% end -%>
</select>

Same thing the Rails way


<%= select('Sec2Override',
           'field',
           [""].concat( Security2Risk.column_names.sort).map{|f| [f,f]},
           {},
           {:onchange=> remote_function( :url => {:action =>"disable_column_for_field"},
                                                  :with => "'field_name='+$(Sec2Override_field).value")}) %>

How do you “options_for_select” when you have multy select drop down ?

I did very hackish overwright of select with multiple=multiple. I’ve seen many tutorials out there that were achiving the same but they were a bit different and mostly were dealing with has_many type of data. In my case all I have a multy select box coming from a single table so the solutions from outhere were super complicated and even less understandable, so I wrote the following plugin.


def cust_opt_for_select(container=[],selected_ids=[],options={})   
    selected_ids = [] if selected_ids.blank?
    container=[] if container.blank?
    container.inject(%()) do |result,(name,id)|  
       result << %(<option value="#{id}"#{" selected='selected'" if selected_ids.include?(id.to_s)}>#{name}</option>) 
    end    
  end

Test

describe MyHelper, "cust_opt_with_select" do

  before(:each) do 
    @container = [["obj1","1"],["obj2","2"],["obj3","3"]]
    @selected_ids = ["2","3"]
    @expected_result = %(<option value="1">obj1</option><option value="2" selected='selected'>obj2</option><option value="3" selected='selected'>obj3</option>)

  end  

  it "should not raise errors when called" do
    lambda{
      cust_opt_for_select(nil,nil)
    }.should_not raise_error
  end 

  it "should return right content with obj2 and obj3  set as selected" do
    cust_opt_for_select(@container,@selected_ids).should ==  @expected_result 
  end  
end