﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-旅行的意义-文章分类-RoR</title><link>http://www.blogjava.net/bacon/category/35728.html</link><description /><language>zh-cn</language><lastBuildDate>Mon, 03 Nov 2008 10:14:35 GMT</lastBuildDate><pubDate>Mon, 03 Nov 2008 10:14:35 GMT</pubDate><ttl>60</ttl><item><title>[Agile Web Development with Rails 3rd]depot疑难杂症</title><link>http://www.blogjava.net/bacon/articles/238376.html</link><dc:creator>bacon</dc:creator><author>bacon</author><pubDate>Mon, 03 Nov 2008 09:04:00 GMT</pubDate><guid>http://www.blogjava.net/bacon/articles/238376.html</guid><wfw:comment>http://www.blogjava.net/bacon/comments/238376.html</wfw:comment><comments>http://www.blogjava.net/bacon/articles/238376.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bacon/comments/commentRss/238376.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacon/services/trackbacks/238376.html</trackback:ping><description><![CDATA[<p><font style="background-color: #fffad0">depot项目任务E check out一章很长，最后playtime中有两个题。<br />
(1)在checkout.html.erb页面不应该还有 [checkout] 按钮<br />
(2)把payment_type字段分离成一个表。</font></p>
<p><font style="background-color: #fffad0">第一个相对简单一点，最省事儿的办法是，设置一个标志字段，然后在layout/store.html.erb中判断一下。<br />
第二个就比较复杂，<br />
(1) generate migration, 重建数据表，修改数据表<br />
(2) generate model PaymentType ,修改Order，添加一对一的映射关系。<br />
(3) 修改store_controller，在checkout中加入@payment_types的取得方法，将对应的view中select部分的静态数组改成这个@payment_types。<br />
(4)因为这个payment_type比较特殊，在order里头并不保存type的id，而是保存name（就是缩写），所以编码的时候需要注意字段的对应关系。不过注意一下的话，问题不大。</font></p>
<p><font style="background-color: #fffad0">结果，第二个跑出来有问题，在checkout页面输入订单信息并选择支付方式，全通过，则没问题，数据库里也都正确。但是一旦有任何输入为空或不合预期，则报错：</font></p>
<p><font style="background-color: #fffad0">&nbsp;</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000">You&nbsp;have&nbsp;a&nbsp;nil&nbsp;object&nbsp;when&nbsp;you&nbsp;didn't&nbsp;expect&nbsp;it!<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />You&nbsp;might&nbsp;have&nbsp;expected&nbsp;an&nbsp;instance&nbsp;of&nbsp;Array.<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />The&nbsp;error&nbsp;occurred&nbsp;while&nbsp;evaluating&nbsp;nil.map</span></div>
<p></font>&nbsp;</p>
<p><font style="background-color: #fffad0">傻了&#8230;&#8230;<br />
因为对payment_type的获取方法也不是很肯定，所以一开始怀疑问题出在表结构映射关系上，反复检验后没发现问题。<br />
然后怀疑页面传参问题，参数传不到这种rp问题&#8230;&#8230;加之之前有几处rails版本区别，觉得对rails的一些约定还是不太了解。<br />
然后试着修改页面，将checkout view的select那一段<br />
</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000">collection_select&nbsp;:pay_type,:name,@pay_types,:name,:display_name,<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;options</span><span style="color: #000000">=</span><span style="color: #000000">{:prompt</span><span style="color: #000000">=&gt;</span><span style="color: #800000">"</span><span style="color: #800000">Select&nbsp;a&nbsp;payment&nbsp;type</span><span style="color: #800000">"</span><span style="color: #000000">}</span></div>
<p><br />
改成</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;@pay_types&nbsp;then<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;collection_select&nbsp;:pay_type,:name,@pay_types,:name,:display_name,<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;options</span><span style="color: #000000">=</span><span style="color: #000000">{:prompt</span><span style="color: #000000">=&gt;</span><span style="color: #800000">"</span><span style="color: #800000">Select&nbsp;a&nbsp;payment&nbsp;type</span><span style="color: #800000">"</span><span style="color: #000000">}<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">else</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;form.select&nbsp;:pay_type，PaymentTypes::STATIC_TPYES,<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;:prompt</span><span style="color: #000000">=&gt;</span><span style="color: #800000">"</span><span style="color: #800000">Select&nbsp;a&nbsp;payment&nbsp;type</span><span style="color: #800000">"</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />end</span></div>
<p><br />
</font>&nbsp;</p>
<p><font style="background-color: #fffad0">页面倒是不会出错了，不过心里总留了一个疙瘩，而且事实上每次出错后都会从PaymentTypes::STATIC_TPYES中取支付类型，也不符合playtime的初衷。这说明某些情况下@pay_types的确是nil了，但是反过来，为啥呢？<br />
忽然一下想起，要是@pay_types为空的话，第一个去按钮的任务也应该不成功，检查了一下，的确如此。</font></p>
<p><font style="background-color: #fffad0">但checkout页面确确实实的显示出来了，说明checkout view被调用了，然而参数是空的。这是我想到看看checkout之后有些什么操作——<br />
checkout提交到save_order，成功则重定向到Index，而失败则render到checkout页面。<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/bacon/render_redirect.JPG" border="0" /><br />
<br />
注意到这里的render。render和redirect_to都会根据checkout.html.erb的内容进行布局，而二者的区别在于，redirect_to会重定向到action对应的函数中重新执行，而render则不会。具体在这里区别就是render不会执行checkout里关于获取<br />
@pay_type的那一段逻辑，从而导致@pay_type为空，自然呈现出来的html中@pay_type就会出错。</font></p>
<p><font style="background-color: #fffad0">在save_order里面加上生成@pay_types的初始化方法，刷新之后问题解决。<br />
问题应该是找到了，但不知道是不是最好的解决办法。因为save_order和checkout中存在代码重复，可以考虑重构一下。</font></p>
<p><font style="background-color: #fffad0"><br />
</font>&nbsp;</p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/bacon/aggbug/238376.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacon/" target="_blank">bacon</a> 2008-11-03 17:04 <a href="http://www.blogjava.net/bacon/articles/238376.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>