I commonly create helper function to make <select> tags with pre-built
options so I can just do something like:
<%=region_select_tag(default_region)%>
to generate a dropdown of values in my views. The helper function
already knows the options to choose from. I usually make three different
versions of each select helper. For example:
* region_options_for_select(selected=nil, options={})
* region_select_tag(name, selected=nil, options={}, html_options={})
* region_select(object, method, options, html_options={})
This API is meant to mimic the Rails select helpers. It gives me just
the options if I want a custom <select> tag, or it can give me the
select tag, or it can work of an object and attribute.
I have many of these and I want to dry up my code. For the most part the
only difference between all my select helpers is the
XXXX_options_for_select() method which actually defines the list. For
example here is a following sample implementation:
**************************
def time_length_options_for_select(selected=nil, options={})
time_lengths = TimeLength.find :all, :order=>''length''
select_blank(select_options options) +
options_from_collection_for_select(time_lengths, ''id'',
''name'', selected.to_i)
end
def time_length_select_tag(name, selected=nil,
options={}, html_options={})
select_tag name, time_length_options_for_select(selected,
options), html_options
end
def time_length_select(object, method, options={}, html_options={})
object, method = object.to_s.dup, method.to_s.dup
selected = instance_variable_get("@#{object}").send method
time_length_select_tag "#{object}[#{method}]", selected,
options, html_options
end
**********************************
Called in the code is two utility functions that are defined as follows:
**********************************
def select_options(options)
options = {
:include_blank => false,
:prompt => false,
}.merge options
options[:include_blank] = true if options[:prompt]
options
end
def select_blank(options)
return '''' unless options[:include_blank]
options[:prompt] = '''' unless options[:prompt].instance_of?
String
content_tag ''option'', options[:prompt], {:value =>
''''}
end
*********************************
So my goal is to change the three time_length_* functions into one
statement that looks like:
*********************************
select_helper :time_length do |selected|
time_lengths = TimeLength.find :all, :order=>''length''
options_from_collection_for_select(time_lengths, ''id'',
''name'', selected.to_i)
end
*********************************
So I tried an implementation that looks something like the following
defined in ApplicationHelper:
def self.select_helper(name, &block)
name = name.to_s
define_method "#{name}_options_for_select" do |*a|
select_blank(select_options(a[1] || {})) + block[a[0] || nil]
end
define_method "#{name}_select_tag" do |n, *a|
select_tag n, self.send("#{name}_options_for_select".to_sym,
(a[0] || nil), (a[1] || {})), (a[2] || {})
end
define_method "#{name}_select" do |object, method, options, *a|
object, method = object.to_s.dup, method.to_s.dup
selected = instance_variable_get("@#{object}").send method
self.send "#{name}_select_tag".to_sym,
"#{object}[#{method}]", selected, (a[0] || {}), (a[1] || {})
end
end
************************************
As you can see the implementation is a bit complicated because I want to
keep the arguments flexible but if I can implement it correctly I will
be able to reduce a lot of code and make it very quick to write a custom
select helper. The problem is that I have some sort of scope problem. I
get a message like the following:
undefined method `options_from_collection_for_select'' for
ApplicationHelper:Module
It seems that it cannot see the helper method defined by Rails. I''m new
to the meta-programming so I''m having difficulty getting the
implementation correct. Any help would be greatly appreciated.
Eric
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk
-~----------~----~----~----~------~----~------~--~---