www.flickr.com
Michael Kovacs' photos More of Michael Kovacs' photos
Recommend Me Cable Car Software logo

Wednesday, January 04, 2006

Rails realities part 3 (First rails enhancement/bug fix)

I didn't expect my next post to be so quick but this cropped up tonight while I was working on my app.
This is just a quick post for anyone else that may need to use a date_select more than once on a page. Here's some code:

< %=date_select(:borrower_profile, :date_of_birth, :order => [:month, :day, :year], :start_year => Time.new.years_ago(7).to_date.year,
:end_year => Time.new.years_ago(104).to_date.year, :include_blank => true, :index => index)% >


In the above snippet creates a set of select widgets to obtain a birthdate with rails' date_select helper method. The problem is that I'm using this helper to obtain birthdates for many users which means I need some sort of index value to track which birthday is attached to which user.

So basically I need HTML like the following to appear in my page:

< select name="borrower_profile[2][date_of_birth(2i)]" > <-- month
< select name="borrower_profile[2][date_of_birth(3i)]" > <-- day
< select name="borrower_profile[2][date_of_birth(1i)]" > <-- year


The :index => index part of my tag in the first code snippet is what is supposed to provide the index value in my select name value "borrower_profile[2]" (2 is the index value).

As it is rails 1.0 and earlier will always ignore :index and generate: "borrower_profile[date_of_birth(2i)]", etc

As it turns out the date_helper method doesn't recognize the :index parameter which many, if not all, other form helper methods do recognize (text_field, select, radio_button, etc). This is most likely just an oversight. At any rate I can't wait for this to be fixed as I need this right now so I dug into rails and fixed it myself.

With some help on IRC I figured out the easiest way to create a patch for rails and have it as part of my app until I can submit it or file a bug to have it fixed in a future release. Anyway, the fix is as follows (This assumes you want to apply the patch from your app and not your rails installation. If not then you can just make the changes outlined below in your rails installation):

1) Paste the following code into a file called date_helper.rb and place it into your application's lib directory.

require "date"

module ActionView
module Helpers
class InstanceTag #:nodoc:
include DateHelper

alias :__to_date_select_tag :to_date_select_tag

def to_date_select_tag(options = {})
defaults = { :discard_type => true }
options = defaults.merge(options)

# begin patch
if options[:index]
@index = options[:index]
options_with_prefix = Proc.new { |position| options.merge(:prefix => "#{@object_name}[#{@index}][#{@method_name}(#{position}i)]") }
else
options_with_prefix = Proc.new { |position| options.merge(:prefix => "#{@object_name}[#{@method_name}(#{position}i)]") }
end
# end patch

date = options[:include_blank] ? (value || 0) : (value || Date.today)

date_select = ''
options[:order] = [:month, :year, :day] if options[:month_before_year] # For backwards compatibility
options[:order] ||= [:year, :month, :day]

position = {:year => 1, :month => 2, :day => 3}

discard = {}
discard[:year] = true if options[:discard_year]
discard[:month] = true if options[:discard_month]
discard[:day] = true if options[:discard_day] or options[:discard_month]

options[:order].each do |param|
date_select << self.send("select_#{param}", date, options_with_prefix.call(position[param])) unless discard[param]
end

date_select
end
end
end
end

2) Place a require 'date_helper' in your environment.rb file
3) restart your webserver
4) use the date_select helper function with the :index option and you'll see your field indexed properly. yay!

Enjoy!

Comments:
Thank you Michael, you saved me from a bit of an headache ;)
 
Hai Michael,
Thank you very much. Your patch is exteremely good.I solved my prolem with very ease
 
Thanks, I applied the patch and it works. Unfortunately, the select helper does not recongnize the :index paremeter either. I tried patching form_tag_helper in a couple of ways but have yet to succeed. The thing is I am new to Rails (and Ruby!) and do not have a very good understanding of the internals. Any help would be appreciated.
 
Thank you. I thought that this should be fixed in rails 1.1.2 but it didn't worked for me. Found this fix from you, thank you again.
 
Thanks heaps for that, JtH.
 
In response to anonymous on March 1st:

The :index can be passed in with the html_options parameter (in the select function anyway), this isn't very clear in the docs if you ask me though, but that's how the source reads.
 
The select function seems to accept :index in 1.1.6, however the date_select still does not. Thanks for saving my day.
 
Thanks. This heled me a lot in my project.
 

Post a Comment





<< Home

This page is powered by Blogger. Isn't yours?