# Select Helper

**URL:** <https://www.ruby-forum.com/t/select-helper/71558>\
**Category:** Rails\
**Created:** [October 9, 2006, 10:24pm UTC](https://www.ruby-forum.com/t/select-helper/71558 "2006-10-09T22:24:46Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![xmg-eric](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/x/f04885/32.png) [@xmg-eric](https://www.ruby-forum.com/u/xmg-eric)\
**Post date:** [October 9, 2006, 10:24pm UTC](https://www.ruby-forum.com/t/select-helper/71558/1 "2006-10-09T22:24:46Z")

</div>

I commonly create helper function to make 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 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

---

<div class="post-metadata">

**Author:** ![xmg-eric](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/x/f04885/32.png) [@xmg-eric](https://www.ruby-forum.com/u/xmg-eric)\
**Post date:** [October 10, 2006, 9:11am UTC](https://www.ruby-forum.com/t/select-helper/71558/2 "2006-10-10T09:11:21Z")

</div>

> 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

Do you get this error when you call select\_helper (where are you calling  
that) or when you call the methods you have defined (and where do you  
call those ?)

Fred

---

<div class="post-metadata">

**Author:** ![xmg-eric](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/x/f04885/32.png) [@xmg-eric](https://www.ruby-forum.com/u/xmg-eric)\
**Post date:** [October 10, 2006, 3:14pm UTC](https://www.ruby-forum.com/t/select-helper/71558/3 "2006-10-10T15:14:51Z")

</div>

Frederick C. wrote:

> Do you get this error when you call select\_helper (where are you calling  
> that) or when you call the methods you have defined (and where do you  
> call those ?)

I get the error when I call the methods defined. I call them from a  
view.

Eric
