`

基于model动态地ComboBox为生成options

阅读更多
在使用RoR创建form时,很多时候需要基于model之间的关系创建ComboBox。RoR提供了很多方便的helper方法帮助我们完成一个 form的创建。例如,如果想要为article创建一个form,并且要为article选择category时,可以使用如下方法:
<% form_for(:material, :url => url, :html => { :method => method }) do |f| %>
  <p><label>Name</label><br/>
  <%= f.text_field :name %></p>
  <p><label>Category</label><br/>
  <%= f.select :category_id, get_category_select_options %></p>
  <p><label>Content</label><br/>
  <%= f.text_area :content %></p>
  <p><%= submit_tag 'Create' %></p>
<% end %>

而其中的get_category_select_options可以采用如下实现方式(定义在articles_helper中):
def get_category_select_options  
  Category.find(:all, :order => 'name').collect { |item| [item.name, item.id] }.insert(0, ['Please select...', nil])  
end

以上代码通过Category类找到所有的category,然后使用其中的name和id属性(注意顺序)作为options的label和data,最后在加入一个默认的选项“Please select...”。一切都很简单,不是吗?

然而,如果model之间的关联稍微复杂一点儿,就可能会在很多地方使用类似的方法获得ComboBox的选项,那么为每个可能成为ComboBox选项的model都写这么一个方法实在是太麻烦了。如果是在Java世界中,我们可以很快想到使用反射来解决这个问题。也就是说在知道类名的情况下,用 Class.forName得到Class对象,然后在调用其上的find方法之类的。但是我们使用的是Ruby这个号称动态能力超强的语言,有什么更容易的做法吗?当然,代码如下:
def get_select_options_for(symbol)  
  Object.const_get(symbol.to_s.capitalize).find(:all, :order => 'name').collect { |item| [item.name, item.id] }.insert(0, ['Please select...', nil])  
end

关键就在这个const_get方法上,它是Module的一个静态方法,所以我们可以通过Object来调用它。我们把类名传递进去,它就可以返回这个类。但是注意这里的写法,我们可以在返回类上直接调用find,而不是像Java那样clazz.getMethod(...).invoke (...),是不是非常的方便呢?我们可以把这个方法定义在application_helper中,这样在所有的view中就都可以使用了,那么上面的 form代码就变成了如下这样:
<% form_for(:material, :url => url, :html => { :method => method }) do |f| %>
  <p><label>Name</label><br/>
  <%= f.text_field :name %></p>
  <p><label>Category</label><br/>
  <%= f.select :category_id, get_select_options_for(:category) %></p>
  <p><label>Content</label><br/>
  <%= f.text_area :content %></p>
  <p><%= submit_tag 'Create' %></p>
<% end %>
分享到:
评论

相关推荐

    easyui使用技巧

    使用 JavaScript 动态生成上述 DOM 后,需要调用 `$.parser.parse()` 方法来触发渲染: ```javascript $.parser.parse($('#tt').parent()); ``` 注意,这里必须解析父元素,因为 `.parser.parse()` 只会渲染目标...

    Jquery LigerUI 中文 API

    jQuery LigerUI 是一款基于 jQuery 的前端组件库,它提供了一套完整的用户界面解决方案,适用于快速构建功能丰富的 Web 应用程序。LigerUI 包含了大量的组件,如表格、表单、对话框、下拉菜单等,大大简化了前端开发...

    struts2的s标签

    Struts2框架是Apache软件基金会下的一个开源项目,它提供了一种基于MVC(Model-View-Controller)设计模式的Web应用开发框架。Struts2提供了丰富的标签库,其中“S标签”(S-tags)是一种特殊的标签集合,用于简化...

    struts2.0的标签库

    Struts2框架的核心设计思想是MVC(Model-View-Controller)模式的应用,该模式将业务逻辑与用户界面分离,使程序结构清晰、易于维护和扩展。在Struts2框架中,标签库(Tag Library)扮演着非常重要的角色,通过这些...

    Tapestry字典0.1.pdf

    - **属性**: `model`, `options`, `optionLabel`, `optionValue`等。 **1.6 使用日历工具 (DatePicker)** - **功能**: 用于让用户选择日期。 - **实现**: 使用`&lt;tapestry:datePicker&gt;`标签。 - **属性**: `value`, ...

Global site tag (gtag.js) - Google Analytics