对Rails的一个简单的练习
一个学生和教师的CRUD,以及简单的ajax应用。学生和教师为多对一得关系
model为:
class Student < ActiveRecord::Base belongs_to :teacher end class Teacher < ActiveRecord::Base has_many :students,:dependent=>:delete_all end
migrate为:
class CreateTeachers < ActiveRecord::Migration def self.up create_table :teachers,:force=>true do |t| t.column :name,:string end end def self.down drop_table :teachers end end class CreateStudents < ActiveRecord::Migration def self.up create_table :students,:force=>true do |t| t.column :name,:string t.column :teacher_id,:integer add_index :students,:teacher_id end end def self.down drop_table :students end end
执行rake db:migrate 后,可以看到没有在数据库中使用外键,只是在teachar_id上面增加了索引
控制器代码: 功能为列出所有的学生和教师,增加和删除学生与教师
#coding:utf-8 class HomeController < ApplicationController #默认页面 def index list render :action => "index" end # 如果提交的姓名不为空,则增加学生,然后跳转到index def new # 如果姓名不为空则执行保存操作 if check_n entity = Student.new unless params[:teacher_id].nil? unless params[:teacher_id]=="0" entity.teacher = Teacher.find params[:teacher_id] end end if check_type == "teacher" entity = Teacher.new end entity.name = @name entity.save flash[:error] = "OK" end redirect_to :action => "index" end # 删除学生/老师 def delete begin # 根据类型进行判断,执行对应代码 logger.debug "debug=================================" logger.debug "the type and id is type:#{params[:type]},id:#{params[:id]}" if params[:type] and params[:type]=="student" Student.destroy(params[:id]) else t = Teacher.find params[:id] # 取得级联删除的学生的id id_array = t.student_ids.to_s t.destroy logger.debug "debug=================================" logger.debug "the array is #{id_array.to_s}" end rescue =>e logger.debug(e) #如果删除失败则不返回任何信息 # render :text => e.to_s return end # 如果是删除老师则返回一个包含有级联删除的学生id的数组字符串 if id_array.nil? render :text => "OK" else render :text => id_array end end private # 列出所有的学生和老师 def list @students = Student.find :all @teachers = Teacher.find :all @teacher_name = [] for st in @students th = st.teacher unless th.nil? @teacher_name << st.teacher.name else @teacher_name << "none" end # logger.debug "debug=================================" # logger.debug "the student's teacher is #{st.teacher}" end end # 检测提交的姓名是否为空 def check_n @name = params[:name] logger.debug "debug=================================" logger.debug "this name is #{@name}" if @name.nil? or @name.strip.empty? flash[:error] = "name should not be empty." return false else return true end end #判断要保存的是学生还老师 def check_type type = params[:type] logger.debug "debug=================================" logger.debug "the type is #{type}" if type.nil? raise "未知的类型。" elsif type == "student" return type elsif type == "teacher" return type else raise "未知的类型" end end end
index.rhtml如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <base href="/"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <title>test</title> <script type="text/javascript" src="javascripts/prototype.js"></script> <script type="text/javascript"> function addEvent(){ //为每个a标签注册单击事件 $$("a").each(function(a){ a.observe("click",deleteEntity) }) } //给教师列表注册时间晕 function teacherList(){ select = document.getElementById("type") value = select.options[select.selectedIndex].text if (value=="学生") $('teacher_id').show() else{ $("teacher_id").hide() } } // 取得数据的id和类型然后调用Ajax请求 function deleteEntity(e){ a = Event.element(e) //取得a标签的id内容,此为要删除的数据在数据库中的主键id id = a.identify() type = "student" if(a.hasClassName("teacher")){ type="teacher" } //向后台发送删除请求晕 ajax(a,id,type) } function ajax(a,id,type){ // alert(id) new Ajax.Request("home/delete",{parameters:{id:id,type:type},onSuccess:callback}) function callback(data){ //取得服务器返回的处理结果 var result = data.responseText removeLi(a) //如果返回的不是OK,则刷新学生列表晕 if (result!="OK") refreshList(result) } } function refreshList(array){ ids = eval(array) if(ids.length==0) return $$("ul")[0].childElements().each(function(li){ li.childElements().each(function(a){ id = a.identify() for(i=0;i<ids.length;i++){ if (id == ids[i]) removeLi(a) } }) }) } function removeLi(a){ a.ancestors()[0].remove() } // 添加事件 Event.observe(window,"load",addEvent) </script> </head> <body> <p>所有学生:</p> <ul> <% @students.each_index do |index| %> <li> 学生姓名:<%=@students[index].name%> 所属的教师:<%=@teacher_name[index]%> <a href="javascript:void(0);" class="student" id="<%=@students[index].id%>">删除</a> </li> <%end%> </ul> <p>所有教师:</p> <ul> <% @teachers.each do |teacher| %> <li> 教师姓名:<%=teacher.name%> <a href="javascript:void(0);" class="teacher" id="<%=teacher.id%>">删除</a> </li> <%end%> </ul> <p /> <hr /> <p>增加学生/教师<br /></p> <% form_tag("home/new") do-%> 姓名:<input name="name"/> <p /> 类别: <select onchange="teacherList()" name="type" id="type"> <option value="student">学生</option> <option value="teacher">教师</option> </select> <div id="teacher_id"> 所属的教师: <select name="teacher_id"> <option value="0">暂无</option> <% @teachers.each do |teacher| %> <option value="<%=teacher.id%>"><%=teacher.name%></option> <%end%> </select> </div> <p /> <input type="submit" value="确定"/> <%end-%> <p>处理结果:<span style="color: red"><%=flash[:error]%></span></p> </body> </html>
上面的
//给教师列表注册时间晕
//向后台发送删除请求晕
最后的'晕'如果不加上,就会出现这个错误 invalid byte sequence in GBK。很诡异啊,可能是bug吧。看了下rubyAPI文档,发现添加Encoding.default_internal="UTF-8"和Encoding.default_external="UTF-8"到application_controller.rb中就可以解决这个诡异的问题。
还有个问题:如果表单输入中文,即数据库中存入中文时还是会报 incompatible character encodings: GBK and ASCII-8BIT的错误
ruby为ruby1.9.1版本
rails为rails2.3.8版本