rails中使用form.select创建动态的下拉菜单
2008-07-22 17:37:07
版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://fsjoy.blog.51cto.com/318484/89010 |
在很多时候,下拉菜单选项是专门做一张查询表,显示里面的某个字段,这张查询表可能会被经常改动。所以,动态的下拉菜单是常见的。举个例子:
在depot的实例中,收集订单信息时,有一项是选择付款方式,原例中是做成了一个死的数组形式,针对这个例子,下面进行改进,将这个死的下拉菜单变成动态形式。
首先对于form.select方法来说,接受参数第一个是对象的字段,第二个是一个数组,数组的形式是[[display1, value1],[display2, value2],[display3, value3]] display对应于下拉菜单的选项显示内容, value是要存入对象字段的值。
理解了这点之后,我们着手改进。
思路是新建一个pay_types的表,里面存储付款类型和id号,在orders中修改pay_type字段为pay_type_id字段,作为外键与pay_types表进行约束。
那么现在pay_types表中的两个字段用来构造上面那个数组[[display1, value1],[display2, value2],[display3, value3]] ,其中付款类型为display, id为value。在最终提交表单的时候将value存到orders表的pay_type_id字段。
实现过程以及代码如下:
首先是数据迁移的代码:
1
class CreateOrders < ActiveRecord::Migration def self.up create_table :orders do |t| t.column :name, :string t.column :address, :text t.column :email, :string t.column :pay_type_id, :integer, :null=>false end end def self.down drop_table :orders end end 2
class CreatePayTypes < ActiveRecord::Migration
def self.up create_table :pay_types do |t| t.column :tp, :string, :null=>false #付款类型 end end #SQL语句,建立约束
execute "alter table orders
add constraint fk_order_pay_types foreign key (pay_type_id) references pay_types(id)" def self.down drop_table :pay_types end end 在Order模型类中加 belongs_to :pay_type
在PayType模型类中加has_one :order
收集订单信息
... <fieldset> <legend> Please Enter Your Details </legend> <%form_for :order, :url=>{:action=>:save_order} do |form|%> <p> <label for="order_name">Name:</label> <%=form.text_field :name, :size=>40%> </p> ... <p> <label for="order_pay_type">Pay with:</label> <%=form.select :pay_type_id, @types, :prompt=>"select a payment method"%> </p> <%=submit_tag "Place Order"%> <%end%> </fieldset> ... 这个@types在checkout这个action中这样定义:
@types=PayType.find_types 在PayType类中定义find_types:
#类方法,生成数组
def self.find_types PayType.find(:all, :order => 'tp').collect { |type| [type.tp, type.id] } end 在Order类中加入验证:
validates_presence_of :name, :address, :email validates_format_of :email, :with=>/^[a-zA-Z0-9_\.]+@[a-zA-Z0-9-]+[\.a-zA-Z]+$/ validates_inclusion_of :pay_type_id,:in => PayType.find_types.map{|disp,value| value} ------------
但是,当所有数据全部填写正确,下拉菜单中选择了付款方式后,一切都没问题,但是如果有一项没有填写正确,包括下来菜单,也就是说无论当order对象的哪个字段成为null值,就会报错。错误信息如下:
You have a nil object when you didn't expect it!
You might have expected an instance of Array. The error occurred while evaluating nil.inject Extracted source (around line #25): 期待解决。。。
在AllenYoung 的文章中介绍了一个方法,当model变得多且复杂,要用到的下拉菜单多的情况下可以在applicationhelper.rb中定义下面的方法:
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 本文出自 “李骥平” 博客,请务必保留此出处http://fsjoy.blog.51cto.com/318484/89010 本文出自 51CTO.COM技术博客 |


fsjoy1983
博客统计信息
热门文章
最新评论
友情链接
