浏览 2799 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-06-17
<% 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 %> 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |