在railscast关于check box讲解的那一集里,提到了check box在habtm中的用法,简单的说一下,还是通过实例:
现在有product和category两个模型,
那么在模型中声明:
#category
has_and_blongs_to_many products
#product
has_and_blongs_to_many category
还要记得加上中间的连接表categories_products,加上外键字段product_id, category_id
在数据库迁移中,product有name:string,在category中也加上
一切都搞定之后,重点看视图中的内容,就是在new和edit模板引用的那个_form局部模板中在submit按钮之前,添加下面的代码:
<%= check_box_tag "product[:category_ids][]",
category.id,
@product.categories.include?(category)%>
<%= category.name%>
<% end %>
product[:category_ids][]是check box 的name属性,这里声明为一个数组.
category.id 是check box对应的value属性
@product.categories.include?(category) 这是默认选择的设置,在edit调用时,@product是传入的对象,执行这句会得到true 或者false,也就会出现对应的是否默认checked
那么还有一点注意的就是当check box 不提交任何内容的时候,在发送params时,product[:category_ids][]数组就不出现在参数里,所以也就不会在action中执行任何动作.
所以在update这个action中,一定要说明product[:category_ids][]为空情况该怎么办:
params[:product][:category_ids] ||=[]
这就告诉rails在update动作的时候注意params[:product][:category_ids]到底有值传过来没有,如果没有就赋为空数组.
剩余的事情就交给rails来搞定了..因为这里的product的category_ids方法是habtm里自带的,所以你可以这么用
但是换种情况,通过has_many , through来连接两个模型呢?
下面通过一个例子来说明:
譬如在学生选课系统中,因为中间表要加入成绩字段,所以必须做成是has_many , through方式来实现.
环境mac, rails 1.2.5 , mysql5.0, IDE:textmate
首先打开[url]http://localhost:3000/courses[/url]
添加几项course数据
在students/view中把new和edit的那段表单代码放到_form.rhtml中,修改之后如下:
因为这里关系已经不是habtm了,所以如果提交表单的话会出现错误,所以在student.rb中写入 course_ids=
这里是一个数组计算的问题,那么怎么更新relations中的数据呢,对于某一个student对象来说,设提交的数组为commit_array, 原先存在数据库中的关系数组为db_array, 那么需要添加的数据就是commit_array-db_array, 需要删除的数据就是db_array-commit_array
举个例子来说
如果提交的commit_array为[1,2,3,4]原来数据库中存储的是[1,2,3]很明显,需要在数据库中添加[4],也就是commit_arry-db_array
如果提交的commit_array为[1,2],原来数据库中存储的是[1,2,3,4]那么,需要删除[3,4]也就是db_array-commit_array
这样就实现了这个_ids的属性.