Rails 求解:关于表间关联

douya0808 · 2012年04月10日 · 最后由 douya0808 回复于 2012年04月14日 · 4090 次阅读

老师 课程 班级 多对多 多对多

根据老师可以查到该老师上哪些课程,再根据哪些班级有该课程可以查到班级,既:该老师都教哪些班级

但是这是理想情况,一般一门课程都有不只一个老师教,这样根据老师查出来的就是所有上这门课的班级,而不是该老师教的该门课的班级 所以我不知道该怎么办了=.=求指导 把多对多会用了我还很高兴来着 没高兴多久就遇到新问题了:)

首先理解你的话费了不少力气

这应该是你所说的理想情况


class Teacher
has_and_belongs_to_many :courses
has_many :school_classes, :through => :courses
end

class Course
has_and_belongs_to_many :teachers
has_and_belongs_to_many :school_classes
end

class SchoolClass
has_and_belongs_to_many :courses
end

不理想的我举个例子,你看看是否符合 比如说有一个课程叫数据结构 10 个班级的同学都要修这课程 分两个老师教,A 教前 5 班,B 教后 5 班 A,B 都教数据机构,但是 A 的班级只是 1-5,B 的班级只是 6-10

我的建议是把数据结构这个课程看成两个课程,意思就是前 5 班级的课程算一个记录,后 5 班级的课程算一个记录。这个也符合逻辑,毕竟在我学校的选课系统中,这是两个选项。这样,你就可以按照以上的理想情况来考虑了。

@davidqhr 多谢多谢啊 我保存下来研究一下:)

Teacher (...) Course (...) SchoolClass (...) Arrangement (teacher_id, course_id, school_class_id)

@davidqhr 数据结构 1 数据结构 2 吗?哈哈 好主意啊

不过,你这 1 和 2 只是名字的区别,内容应该一样

@Rei 这个是带三个的多对多吗?:)

@Rei 多谢多谢 我去瞅瞅 :)

@Rei 你好 我之前只用会 has_and_belongs_to_many 刚才基本学会了用 has_many :througth 但是还是没明白用这种方式如何解决我的问题呢 我目前所能看到的就是这只是另一种多对多关联的写法 求指点:)

老师 课程 班级 多对多 多对多

我所能想到的是老师班级作单独的表,课程作中间表,这个中间表除了老师_id班级_id还有自身的课程信息 :)

我对 has_many :students, :through =>这种方式有个小小的疑问:)

中间表中的数据是 id student_id group_id 1 3 4 2 3 4 3 3 4

id 是主键 student_id 和 group_id 分别是外键 这些都没错 但是这样 3 4,3 4,3 4 的 student 和 group 的关系岂不是重复了吗?求解

用 has_and_belongs_to_many 这种联合主键就不是重复的

假设用这个结构

Teacher (...)
Course (...)
SchoolClass (...)
Arrangement (teacher_id, course_id, school_class_id)

class Teacher
  has_many :arrangements
  has_many :courses, :thougth => :arrangements, :uniq =>true
  has_many :school_classes, :thougth => :arrangements, :uniq =>true
end

class Course
  has_many :arrangements
  has_many :teachers, :thougth => :arrangements, :uniq =>true
  has_many :school_classes, :thougth => :arrangements, :uniq =>true
end

class SchoolClass
  has_many :arrangements
  has_many :teachers, :thougth => :arrangements, :uniq =>true
  has_many :courses, :thougth => :arrangements, :uniq =>true
end

class Arrangement
  belongs_to :teacher
  belongs_to :course
  belongs_to :school_class
end

# teacher 有课的班
teacher.school_classes

刚忘了说还有 :uniq 这个参数,用来去掉重复。

我觉得这个结构是比较灵活的,熟悉 sql 的话可以做各种关联查询。

@Rei 这是用中间表来实现三个表的关联吗?更复杂啦 我得存起来理解下 多谢多谢哟

主要我的思维定势太严重了 我一直就以为多对多就是两张表加一张中间表呢 以前写的玩具最复杂也就这关系了 二了二了 得前辈指导大开眼界呀:)

@Rei 前辈俺有个小问题 :uniq =>true 这个属性不限制往数据库中存储这个操作吗? 例如我可以一直存储成以下形式 id a b c 1 3 5 3 2 3 5 3 3 3 5 3 4 3 5 3 5 3 5 3

我试验存储的时候,存进相同的数据不会报错,但是往外遍历的时候同样的属性值只会得到一次 这个就是:uniq =>true 这个属性的功能所在吗?虽然我试验出了结果但是我不敢肯定呀哈哈

但是这样岂不是很浪费空间吗?例如我存了 100 行相同的数据 虽然我把他们看作一行 但是他们实际上就是存了 100 行呀:)

#16 楼 @douya0808 是的。限制存入用 validates

@Rei 前辈前辈 我遇到了个很棘手的问题 我的中间表是这样的 arrangements 表 id-----teacher_id-----kecheng_id-----banji_id 1----------2------------------4--------------------4 2----------3------------------4--------------------2 3----------1------------------1--------------------1 4----------2------------------1--------------------5
我想就按照表的顺序把表里的内容输出出来,直接输出的话只能显示数字,但是我想把每个字段关联到的名字输出出来,例如下面这样的 1--------田晓光-----------数据结构-----------------网络一班 2--------李兴华-----------操作系统-----------------软工一班 3--------尹晓青-----------编译原理-----------------软工二班

所以我在后台这样遍历

@arrangements=Arrangement.all  #取得所有数据
    @arrangements.each do |arrangement|

       @teacher=Teacher.find(arrangement.teacher_id)
       @teacher_name=@teacher.name    #取得相应id的教师名

       @banji=Banji.find(arrangement.banji_id)
       @banji_name=@banji.name    #取得相应id的班级名

       @kecheng=Kecheng.find(arrangement.kecheng_id) 
       @kecheng_name=@kecheng.name    #取得相应id的课程名
end



前台输出=。=

<%=@teacher_name%><%=@banji_name%><%=@kecheng_name%>



实际上我这样只能得到其中的一行,并不能完全输出表的所有对应字段 前辈指点下我吧:)

实例变量被重复赋值了。应该先在控制器拿到@arrangements,遍历交给视图

控制器

@arrangements = Arrangement.includes(:teacher, :banji, :kecheng).all




视图

<% @arrangements.each do |arrangement| %>
  <%= "#{arrangement.teacher.name} #{arrangement.banji.name} #{arrangement.kecheng.name}" %>
<% end %>




@Rei 看了下数据库字段 我那么写每次输出的都是一行 正如前辈所说是被覆盖了 待我到前台遍历一番:)

@Rei includes 真是个好东西啊 这样根据中间表也能直接取得所关联的实体了 前辈收我为徒吧 开山大弟子:)

@Rei 师傅 徒儿还有一事不明望师傅赐教╯з︶

@arrangements = Arrangement.includes(:teacher,:banji,:kecheng)



我是这样遍历的中间表和中间表所对应的各个实体 但是我在前台遍历的时候还是有重复 不知道为什么在这种情况下 :uniq=>true 属性不起作用了

类似以下重复 教师:----- 课程:------- 班级: 田晓光-- 离散数学 ---软件工程 1 班 田晓光 --离散数学 ---软件工程 1 班 谷丰-------- 英语 -------软件工程 1 班 谷丰-------- 英语 -------软件工程 1 班

我想到了原因,因为如果我只是查找

@arrangements = Arrangement



的话,这样输出的话他会自动去除重复的

但是我查找的是

@arrangements = Arrangement.includes(:teacher,:banji,:kecheng)



的话 结果集的排列结构是这样的

@arrangement @teacher @banji @kecheng
@arrangement @teacher @banji @kecheng
@arrangement @teacher @banji @kecheng



所以 rails 就不会帮我去除重复了,所以我把他们内部的属性输出了也是满页的重复

嘿嘿:) 求指导

#23 楼 @douya0808 查询 Arrangement 本身就不会去重阿,是不是 Arrangement 里面插入了重复的值?

后面排列没看明白。

@Rei 师傅 我想说的就是这贴 16 楼的那个结论 但是我刚才又试了下 我查询查询 Arrangement 没有去重复 但是我那天试验确实是去重复了 忘了我当时是怎么查的了 我再研究下:)

#25 楼 @douya0808 这个要做校验约束唯一值

validates :teacher_id, :uniqueness => { :scope => [:banji_id, :kecheng_id] }

@Rei 师傅我想起来了 我那天试验遍历的是 Banji 中的 teachers 和 kechengs,是把重复的组合形式去掉了 然后遍历 Teacher 中的 banjis 和 kechengs 也会把重复的去掉
因为他们的 model 中都写了:uniq =>true 但是遍历 Arrangement 的时候就不会把重复的去掉了 我可以遍历出一个班级的所有课程 (无重复),和所有任课教师 (无重复),但是无法看出哪门课是哪个老师教的,所以只能遍历 Arrangement,但是不会去掉重复:)

@Rei 师傅你 26 楼那个办法真好 重复了也不会抛异常 只是不往里存罢了 我往外遍历的时候就也不会有重复了 :) 哦耶 又进步了 谢师傅

需要 登录 后方可回复, 如果你还没有账号请 注册新账号