您所在的位置: 首页 > 读书频道 > 设计开发 > 其它开发 >

2.3.3 改进“新增留言”

http://book.51cto.com  2008-04-02 15:06  李刚 郭秋霞  电子工业出版社  我要评论(0)
  • 摘要:《Ruby on Rails敏捷开发最佳实践》第2章向读者示范如何开发一个简单的Rails应用,这个Rails应用是一个简单的留言系统。本文讲了改进“新增留言”。
  • 标签:Rails  新增留言  Ruby on Rails敏捷开发最佳实践

2.3.3  改进“新增留言”

我们希望当新增留言的时候,允许用户上传图片,并能判断上传文件的类型是否为图片和文件是否过大。这在Rails中不难做到,不需要使用任何插件,只用十分简洁的代码即可实现图片的上传功能!这的确是一件让程序员愉快的事情。

在这一节,我们来改进“新增留言”,着重介绍图片上传的实现。

修改/app/views/message路径下的new.rhtml视图文件。修改后的代码如下:

<table width="80%" border=0 align="center" class="pt9" cellpadding=10 cellspacing="1" bgcolor="#BFCAE6">
<tr>
<td>
<p>
<label for="message_name">标题:</label>
<%= @message.title %>
</p>
<p>
<label for="message_description">内容:</label>
<%= @message.detail %>
</p>
<p>
<label for="message_picture">图片:</label>
<!-- 如果留言有图片 -->
<% if @message.has_picture? then %>
<!-- 调用url_for帮助方法,生成一个URL -->
<img height=120 width=120 align="center" src="<%= url_for(:action =>
"show_picture", :id => @message.id) %>"/>
<% else %>
<i>无图片</i>
<% end %>
</p>
<p>
<label for="message_time">留言时间:</label>
<%= show_date(@message.created_at)%>
</p>      
<p>
<label for="message_category">留言人:</label>
<!-- 调用user实例方法,返回Message对象对应的User对象 -->
<%= @message.user.name %>
</p>
<br>      
<%= link_to '返回', :action => 'list' %>
</td>
</tr>
</table>


上面的代码在start_form_tag帮助方法中指定multipart的选项值为true,使得该表单能够发送文件数据。并且,通过调用file_field帮助方法,生成了一个文件域。这里的picture属性只是个虚拟属性,因为在数据库的messages表中并不存在这个属性。这需要我们对这个虚拟属性做一些处理,使之对应messages表中的真实属性。具体实现方式下面会有详细介绍。

上面的表单是没有为留言时间设计表单域的,因为我们可以通过更简便的方式来为Message对象的这个属性赋值:messages表中表示留言时间的字段名为created_at,数据类型设计为timestamp,这样,当保存一条Message对象对应的记录时,Rails就会自动将当前时间赋值给created_at列,而不需要我们手动赋值。

在message_controller.rb控制器文件中,需要修改create方法,修改后该方法的代码片段如下。

def create
# 查找出当前留言的User对象
user=User.find(session[:user_id])
# 将该User对象赋值给参数中Message对象的user属性
params[:message][:user]=user
# 构造一个Message对象,并使用message参数来初始化该对象
@message = Message.new(params[:message])
# 如果Message对象能成功保存进数据库
if @message.save
flash[:notice] = '新增留言成功!'
# 重定向到list Action
redirect_to :action => 'list'
else
# 提交new Action
render :action => 'new'
end
end


在create方法的定义中,前面两句代码是scaffold生成的默认代码中所没有的。这是因为user_id是messages表参照users表的外键列,scaffold不会自动生成对外键列的操作。所以,我们需要根据session[:user_id]来查找出留言的User对象,并把该对象赋值给表单参数中的Message对象,作为它的一个user属性。这样,当Message对象调用save方法保存进数据库的时候,会让该Messge对象对应的数据行参照到该User实例对应的数据行。

在Message Model文件中,重定义一个picture=方法。因为我们的new.rhtml视图文件中有一个picture表单域,当提交表单后控制器将发送一个message[:picture]的请求参数,这个请求参数将要求Message类里包含一个picture=方法,该方法用于接受message[:picture]请求参数。

picture=方法负责把message[:picture]请求参数(这个请求参数值是一个文件对象,里面包含了非常丰富的信息)解析出来。下面是picture=方法的代码:

# 提供picture=方法,将一个picture的表单域设置成Message对象的多个属性 
def picture=(picture_field)
transaction do   
# 如果用户上传了图片
if picture_field.size>0 then
# @picture_size为上传图片的文件大小
@picture_size=picture_field.size
# @picture_type为上传图片的文件类型
@picture_type=picture_field.content_type.chomp
# 设置Message对象的picture_content_type属性
self.picture_content_type =@picture_type
# 设置Message对象的picture_data属性
self.picture_data = picture_field.read
end
end
end


提供了picture=方法之后,我们就将message[:picture]请求参数与messages表中的真实属性picture_content_type和picture_data对应起来了。

在上传文件方面,Rails处理得很好,表单中的文件域参数值不再是一个简单的类型值,而是已经被包装成一个文件对象,它也有size,content_type和read方法,直接调用这些方法,即可返回这个文件对象的大小、文件类型和包含的二进制数据。

当用户添加一条留言时,我们需要对留言对象进行模型校验,这可以通过在message.rb模型文件中重写validate方法来实现。代码如下:

def validate 
# 验证title不能为空
errors.add("", "标题不能为空") if title.empty?
# 验证detail不能为空
errors.add("", "内容不能为空") if detail.empty?
# 下面校验上传的图片
if @picture_type != nil
# 校验上传图片的文件类型
errors.add("", "贴图不是合法的图片文件") unless @picture_type =~ /^image/
end
if @picture_size != nil
# 校验上传图片的文件大小
errors.add("", "贴图文件太大,应不能超过50 KB") if @picture_size > MAX_IMAGE_SIZE
end
end


在上面的代码中,我们校验留言标题、留言内容的值不能为空,上传的文件类型必须是图片形式,并且文件大小不能超过允许上传的最大图片值(MAX_IMAGE_SIZE为允许上传的最大图片值,这个常量在前面的2.3.2节中已经有定义)。

登录留言系统后,在list页面中单击下方的“新增留言”链接,进入新增留言页面。然后在该页面中输入数据,选择一个图片文件上传。如果图片不合法,将会在浏览器中看到如图2.10所示的效果。

图2.10  新增留言时图片不合法 

由图2.10可看到,页面中显示出了错误提示信息,系统仍停留在新增留言的页面。选择一个合法的图片文件,再单击“提交”按钮,才能成功地添加留言。

【责任编辑:雪花 TEL:(010)68476606】

回书目   上一节   下一节
Prototype and script.aculo.us终极揭秘
Red Hat Linux 9系统配置与服务器管理
ARM嵌入式Linux系统开发技术详解
Ubuntu标准教程
嵌入式Linux设备驱动开发详解
 
 验证码: (点击刷新验证码)   匿名发表
  • Linux C编程实战

  • 作者:童永清
  • 本书系统地介绍了在Linux平台下用C语言进行程序开发的过程,集趣味性、实战性于一体的160多段代码实例,帮助读者快速掌握在Linu..
Copyright©2005-2008 51CTO.COM 版权所有