admin 管理员组

文章数量: 1184232


2024年3月9日发(作者:inwrite登录入口)

《RubyonRails敏捷开发最佳实践-精典章节收录》PDF教程申明:本PDF教程由网站搜集整理,如需转载,请务必注明出处。介绍:RubyOnRails框架一经推出,立即引起B/S结构应用开发领域革命性的变化:开发者无需理会架构,只需要按Rails框架的约定向应用中填充代码,一切OK。为了让众多RubyOnRails学习、工作者,以及准备使用RubyOnRails作为开发平台的开发人员能快速掌握RubyOnRails的开发,作者精心编写了本书,书中既详细讲解了Ruby语言的基本语法,又重点介绍了Rails框架相关知识点的各种用法。最后给出两个综合案例,作为RubyOnRails应用开发者的参考,读者可以通过这两个案例触类旁通,解决日常开发中的问题。读者对象本书适用于正在使用RubyOnRails进行应用开发的开发人员、渴望了解RubyOnRails框架的开发人员,尤其适合有初步的JavaEE开发经验,想从JavaEE平台过渡到RubyOnRails开发平台的开发者。(未完待续)

第15章Rails的邮件抽象层本章要点·电子邮件的基础知识·SMTP协议初步·POP3协议初步·在Ruby程序中使用SMTP支持发送邮件·在Ruby程序中使用POP3支持接收邮件·ActionMailer::Base的邮件支持·在Rails应用中发送邮件·发送HTML格式邮件·发送带附件的邮件·电子邮件在实际应用中的用途·账户需要激活的优势·实现注册激活系统15.4注册激活系统本章将介绍一个注册激活系统,当用户输入注册信息时,必须输入有效的邮箱,当用户注册成功后,并不能立即登录系统,而要登录注册时输入的邮箱,然后通过该邮箱内的激活邮件来激活自己账户。通过这种方式可以防止用户恶意注册,保证用户必须输入有效的邮箱地址。15.4.1基本注册功能当用户注册一个账户时,实际上就等同于向底层数据表增加一条记录,因此本应用必须有持久层支持。本示例应用的注册功能需要一个数据表支持,该数据表用于保存系统的所有注册账户。下面是本应用的数据库脚本:dropdatabaseifexistsregist_development;createdatabaseregist_development;useregist_development;--创建用户表createtableusers(idintnotnullauto_increment,

namevarchar(100)notnullunique,passvarchar(100)notnull,emailvarchar(150)notnull,active_codevarchar(255),is_activatedboolean,primarykey(id));上面创建了一个users数据表,该数据表里保存了用户名、密码、E-mail、激活码和是否激活等5个数据列。前三个数据列的作用非常清晰,此处不再赘述。激活码列用于保存用户刚刚注册时系统生成的注册码,这个注册码将通过邮件发送给用户,系统正是通过比较用户输入的注册码和这个注册码是否相等,从而决定是否可以激活用户。上面的users数据表对应的持久化类是User,这个持久化类的代码非常简单,只是增加了一些Model校验功能。下面是User类的代码:classUser请输入您的注册信息

注意:请务必输入有效的邮箱用于接收激活邮件

<%=error_messages_for:user%><%form_for:user,@user,:url=>{:action=>"pro_regist"}do|f|%>用户名:<%=_field:name%>
密 码:<%=rd_field:pass%>

Email:<%=_field:email%>
<%=submit_tag("注册")%><%end%>在浏览器中浏览该页面,看到如图15.8所示的表单页效果。图15.8注册表单当用户单击如图15.8所示的“注册”按钮时,将会把图15.8所示的表单提交到pro_registAction。这个Action也非常简单,它只需调用该User类的create方法向users数据表中增加一条记录即可。下面是处理用户注册的Action代码:#处理用户登录defpro_regist#创建一个新的user对象@user=(params[:user])#以当前时间来随机生成激活码@_code=rand(_i).to_s#设置用户开始处于未激活状态@_activated=false#如果user对象能成功地保存进数据库if@enflash[:notice]='您已经注册成功'flash[:name]=@#发送邮件r_sent(@user)redirect_to:action=>'success'#保存失败elserender:action=>'index'endend

上面的Action方法的实现与普通注册Action代码大致相似,不同的是上面的Action代码需要调用r_sent(@user)代码来发送邮件。这行代码调用ActivateMailModel里的sent方法来发送激活邮件,这也就是本应用实现用户激活的重点。15.4.2发送激活邮件本应用需要向注册用户发送激活邮件,对于Rails应用而言,激活邮件也就是一封最普通的邮件,因此我们像开发普通邮件模块一样来实现发送激活邮件。同样,我们先使用Rails提供的邮件代码生成器来生成一个邮件模块。进入Rails应用的根路径下,输入如下命令:#生成ActivateMail邮件Model,并提供一个sent方法rubyscript/generatemailActivateMailsent上面的代码生成器命令会在app/models路径下生成一个activate_文件,这个文件就是邮件发送Model,该Model里定义了一个sent方法,该方法就是发送邮件的业务逻辑方法。修改上面的sent方法,让该sent方法实现发送激活邮件的功能。修改后的sent方法代码如下:#定义发送邮件的业务方法defsent(user)#指定邮件标题@subject='激活邮件'#将新注册的User实例传给邮件内容模板@body={'user'=>user}#使用用户的注册邮件作为收件人地址@recipients=#使用spring_test@作为发件人地址@from@sent_on@headers='spring_test@'=={}#指定使用HTML格式的邮件@content_type='text/html'end与前面完全类似的是,我们一样采用spring_test@作为发件人地址,这就要求我们必须在config路径下的文件中配置sina的邮件服务器。在文件中增加如下代码:ActionMailer::ry_method=:smtpActionMailer::_settings={:address=>'',:port=>25,:domain=>'',

:user_name=>'spring_test@',:password=>'123456',:authentication=>:login}ActionMailer::t_charset='GBK'经过上面步骤,我们已经实现了发送激活邮件的大部分功能。还有一个必须完成的地方:我们定义sent(user)方法时,该方法为@body赋值的是一个Hash对象,这意味着我们还需要为该方法指定一个邮件模板。当我们执行rubyscript/generatemailActivateMailsent命令时,该命令还在appviewsactivate_mail路径下生成了一个文件,这个模板文件的响应将作为(user)方法发送的邮件内容。模板文件的代码如下:

<%=@%>,您好!

请在浏览器的地址栏中输入如下地址来激活您的账户:
&active_code=<%=@_code%>'>localhost:3000/regist/pro_activate?name=<%=@%>&active_code=<%=@_code%>上面的邮件模板是一个非常简单的页面,这个页面包含了一个简单的超级链接,这个超级链接将向服务器发送两个请求参数:用户名和验证码。如果用户注册结束,登录注册时所输入的邮箱,将可以看到如图15.9所示的界面。图15.9激活邮件用户只要单击如图15.9中的账户激活链接,就可以激活刚刚注册的账户。在还未激活用户账户之前,我们打开users数据表,看到用户刚刚注册的账户信息处于如图15.10所示的状态。

图15.10未激活的用户账户当用户账户被激活后,图15.10中is_activated列的值将变成1,这表明用户账户已被激活。15.4.3处理激活用户单击激活邮件中的链接,相当于向系统的regist控制器的pro_activateAction发送一个请求,并将用户名和激活码作为请求参数,Rails应用将根据这两个请求参数来决定是否激活用户账户。下面是pro_activateAction的代码:#处理用户激活defpro_activateuser=_by_name(params[:name])#如果用户不为空,且用户处于未激活状态,且用户输入的激活码正确ifuser!=nil&&_activated==false&&_code==params[:active_code]then#修改激活状态_attribute(:is_activated,true)flash[:notice]="恭喜您,您已经成功激活了您的账户!"#如果用户已经处于激活状态elsifuser!=nil&&_activated==truethenflash[:notice]="您的账户已经处于激活状态,请勿重复激活!"elseflash[:notice]="激活失败!"endredirect_to:action=>'activate_result'end上面Action先根据发送的name请求参数取出users表中对应的用户账户,然后判断取出的账户里包含的激活码与用户请求中包含的激活码请求参数是否相同。如果两个激活码相同,而且用户还未激活,系统将把用户账户的is_activated属性修改为true,即完成用户激活。如果用户的is_activated状态已经是true,则提醒用户不用重复激活账户。当用户注册成功,并且通过如图15.9所示的激活链接来激活账户后,就可以看到如图15.11所示的界面。

图15.11激活成功一旦成功激活了用户账户,也就是将users数据表中对应记录行的is_activated数据列的值修改为1。15.4.4处理登录增加了激活功能后的用户登录,也增加了额外的处理,除了需要判断用户名和密码是否匹配之外,还必须判断用户账户是否处于激活状态。下面是处理用户登录的Action代码:#处理用户登录defpro_login#根据用户名和密码查询用户user=_by_name_and_pass(params[:user][:name],params[:user][:pass])#如果找不到对应用户ifuser==nilthenrender:text=>'

您输入的用户名和密码不匹配

',:layout=>true#如果用户处于未激活状态elsifuser!=nil&&_activated==falserender:text=>'

您的账户还未激活,请先激活您的账户

',:layout=>true#成功登录elserender:text=>'

您已经成功登录

',:layout=>trueendend从上面的Action代码中可以看出,如果用户输入的用户名和密码匹配,但用户还处于未激活状态下时,系统将提示用户账户还未激活,将看到如图15.12所示界面。

图15.12账户还未激活通过上面示例,我们示范了电子邮件在实际应用中的用途:通过电子邮件来激活账户,可以避免用户注册账户时随意输入电子邮件地址,可以防止恶意注册。15.5本章小结本章主要介绍了Rails应用的邮件支持。本章从电子邮件的基础知识开始讲起,简单地介绍了电子邮件的发展和用途,以及SMTP协议和POP3协议的初步知识,并通过示例示范了如何在Ruby语言中发送和接收邮件。本章重点介绍了Rails的邮件支持,包含如何定义Rails邮件系统配置,如何发送HTML格式邮件,如何发送带附件的邮件。本章的最后还通过一个注册激活系统来示范了电子邮件在实际应用中的用途。第16章Rails和Ajax本章要点·Ajax简介·Ajax技术对传统Web技术的改进·Ajax技术的关键技术·Ajax技术的原理和流程·在Rails应用中手动实现Ajax应用·发送异步请求·异步方式提交表单·周期性地发送异步请求·使用Observer·直接执行服务器响应脚本·使用自动完成·自定义发送异步请求的时机

·实现拖动效果·实现排序效果·各种视觉效果Ajax技术极好地改进了传统Web开发技术,通过使用Ajax技术,允许客户端异步地向服务器发送请求,当服务器响应到达客户端时,客户端页面通过JavaScript自动把服务器响应更新在页面中。通过使用Ajax技术,会极好地改善用户的感觉,用户可以持续发送异步请求。当用户发送请求后,无须等待服务器返回,因为原来的页面内容还存在,用户可以继续前面的操作。当服务器响应到达客户端时,JavaScript负责将服务器响应加载在页面中。Ajax技术是如此有用,因此Rails框架也提供了极好的Ajax支持,Rails框架的Ajax支持以Prototype和为基础。由于Prototype和是如此优秀,以至于它们后来独立成为了优秀的Ajax函数库。尤其是Prototype,只要是进行Ajax开发的开发者,几乎都为它的小巧易用而折服。而Rails则对Prototype和做了进一步封装,更加简化了Ajax开发。通过Rails的Ajax支持,开发者大部分时候无须编写任何JavaScript代码,即可完成优秀的Ajax效果。Rails为大部分Ajax应用场景都提供了极好的封装,开发者只需调用Rails的Ajax方法,即足以应付大部分Ajax场景。16.5Ajax的效果模块:ScriptaculousHelper前面已经介绍了Rails的Ajax主要由Prototype和Scriptaculous组成,前面介绍的Ajax核心模块就是对Prototype的封装。接下来介绍的ScriptaculousHelper则是对Scriptaculous的封装,通过它来实现Rails的富客户端效果。16.5.1拖动效果通过ScriptaculousHelper模块的帮助,允许我们在页面中通过拖动来实现Ajax交互。Rails用以实现拖动效果主要有如下两个方法。·draggable_element:该方法将某个HTML元素定义成一个可以拖动的元素。·drop_receiving_element:该方法将某个HTML元素定义成一个拖动目的地元素。将一个可拖动元素(使用draggable_element定义)拖动到拖动目的地元素(使用drop_receiving_element定义)时,Rails将会向服务器发送Ajax请求。draggable_element方法的用法很简单,它将一个HTML元素定义成一个自由拖动的元素。该方法的语法格式如下:

draggable_element(element_id,options={})该方法将element_id元素定义成一个可自由拖动的元素,其中options用于定义各种拖动选项,其中最常用的选项就是:revert,该选项控制拖动一个元素后该元素是否会回到原来的地方。下面程序示范了使用draggable_element方法来定义可拖动HTML元素。

拖动示例

<%=image_tag("",:id=>"image1")%><%=image_tag("",:id=>"image2")%><%=draggable_element("image1",:revert=>true)%><%=draggable_element("image2",:revert=>false)%>上面的代码两次使用draggable_element定义了2张可拖动图片,其中一张图片被拖动后不会回到原来的地方,而另一张图片则会回到原来的地方,效果如图16.16所示。图16.16可拖动效果这种拖动效果仅仅只是一种视觉上的改变,还未实现任何实质(系统后台)的改变,因为我们的拖动未发送任何Ajax请求。如果我们结合drop_receiving_element方法,将可以实现更强大的功能。使用drop_receiving_element方法的语法格式如下:drop_receiving_element(element_id,options={})

该方法将element_id所指定的HTML元素定义成一个可拖动的目的地。因为该方法会发送Ajax选项,因此可以接受如下几个选项。·:url:该选项指定一个符合url_for格式的URL地址。·:update:该选项指定使用服务器响应来更新哪个HTML元素。除此之外,当然也可指定:complete、:loaded等Ajax交互阶段的特定选项。下面将使用draggable_element和drop_receiving_element实现一个购物车效果。进入购物车页面时,先经过如下Action处理,该Action创建了一个字符串数组作为实例变量。#定义进入购物车的Actiondefcart#如果session[:cart]为nil,则将其赋为{},否则不改变session[:cart]||={}#创建一个字符串数组@books=%w{springajaxstruts2}end在上面的Action中定义了用户的:cartSession,该Session用以跟踪用户的购物状态。还手动构建了一个字符串数组,这个字符串数组将作为系统的商品。提示实际应用中我们可以通过Model从数据库中取出所有商品,但本应用为了简化应用的复杂度,只突出Ajax应用,故没有使用Model进行持久化访问。视图页面将使用draggable_element方法和drop_receiving_element方法来构建通过拖动来购买商品的应用。页面的代码如下:

拖动效果

下面是所有商品

<%@|book|%><%=image_tagbook+".jpg",:id=>book%><%=draggable_element(book,:revert=>true)%><%end%>

将上面商品拖到下面方框中就是购买了该商品

black;">

<%=drop_receiving_element("my_cart",:url=>{:action=>"add"},:update=>"my_cart")%>上面页面会迭代输出@books实例变量中每个元素,并将每个元素都转换成一个可拖动的元素;除此之外,还使用drop_receiving_element方法定义了一个拖动目的地元素,每当元素被拖动到该元素时,Rails将向addAction发送请求,并发送被拖动元素的id作为请求参数。下面是addAction的代码:#定义添加物品的Actiondefadd#取得请求参数product_id=params[:id];#如果请求参数不为空ifproduct_id!=nilthen#如果购物车中的物品已经存在,则数量加1,否则设置该物品数量为1session[:cart][product_id]=session[:cart].include?(product_id)?session[:cart][product_id]+1:1end#使用_页面来生成响应render:partial=>'cart'end从上面的Action代码来看,Rails拖动时会将被拖动元素的id作为请求参数发送到服务器,上面的Action就可以获取用户希望购买的物品,从而可以修改用户的session状态。该Action最后提交到_页面来显示处理结果。该页面的代码如下:<%session[:cart].eachdo|product,quantity|%>
<%o|i|%><%=image_tagproduct+".jpg",:id=>"item_#{product}_#{i}",:size=>"40x60",:style=>"position:relative;"%>

<%end%><%=product%>:<%=quantity%>

<%end%><%="您暂时还未购买任何图书!"ifsession[:cart].empty?%>上面的_页面生成的响应将会用来更新原来页面的my_cart元素,从而可以通过拖动来购买商品,图16.17是上面页面的购物车效果。图16.17基于拖动的购物车效果上面应用的界面更加友好:浏览者可以直接通过拖动鼠标来购买商品,这是很有乐趣的事情。值得指出的,如果希望加载该页面时即显示用户的购物车中有多少商品,应该在用户进入该页面时立即向addAction发送请求(addAction已经处理了没有请求参数的情形)。上面应用已经实现了该功能,我们在body元素load时通过remote_function来发送请求,从而实现了页面加载时立即发送请求的要求。16.5.2使用sortable_element排列列表项sortable_element是另一个可支持Ajax交互的方法,这个方法把页面中多个列表项定义成可上下拖动的元素,通过上下拖动这些HTML元素,从而允许手动对这些列表项进行排序。当用户拖动完成后,Rails会将排序后的元素id以异步方式发送到服务器。使用sortable_element方法的语法格式如下:sortable_element(element_id,options={})

该方法将会把element_id属性对应的HTML元素里所有的列表项变成可排序的列表项。因为该方法会发送Ajax选项,因此可以接受如下几个选项。·:url:该选项指定一个符合url_for格式的URL地址。·:update:该选项指定使用服务器响应来更新哪个HTML元素。除此之外,当然也可指定:complete、:loaded等Ajax交互阶段的特定选项。下面的页面代码将会使用sortable_element方法来把系列列表项转成可排序的列表项。页面代码如下:

可重新排序的列表项

<%@|book|%>"><%=book%><%end%>