﻿<?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>C++博客-qiezi的学习园地-随笔分类-Ruby</title><link>http://www.cppblog.com/cpunion/category/88.html</link><description>AS/C/C++/D/Java/JS/Python/Ruby</description><language>zh-cn</language><lastBuildDate>Mon, 19 May 2008 12:34:08 GMT</lastBuildDate><pubDate>Mon, 19 May 2008 12:34:08 GMT</pubDate><ttl>60</ttl><item><title>[RoR] Post/Get分派</title><link>http://www.cppblog.com/cpunion/archive/2006/09/17/12571.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Sun, 17 Sep 2006 03:13:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2006/09/17/12571.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/12571.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2006/09/17/12571.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/12571.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/12571.html</trackback:ping><description><![CDATA[<b>一、前言</b>
		<br />
		<br />出于数据安全性考虑，某些破坏性链接应该使用post请求，比如一个删除记录的请求。<br /><br />除了脚本确认以外，服务端还需要post验证，因为脚本是可以绕过的。想像你的页面上有一个删除链接，只作了客户端脚本确认（老的scaffold生成代码有这问题），被google找到了，它一个请求就会让你的数据丢失。<br /><br />rails对于这类请求的处理，是通过verify方法，默认的scaffold生成代码有如下内容：<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">  </span><span style="color: rgb(0, 128, 0);">#</span><span style="color: rgb(0, 128, 0);"> GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">  verify </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">method </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">post</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">only </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> [ </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">destroy</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">create</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">update ]</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"><br />         </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">redirect_to </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> { </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">action </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">list }</span></div><br />只有post请求时，destroy才会被允许，如果是get，就会被重定向到list。<br /><br /><b>二、实现</b><br /><br />我自己实现了一个method_dispatch，当请求一个/test/a时，如果是get，则会直接执行TestController#a；如果是post，则会执行TestController#a_post，a_post应该是protected，这样不会直接暴露给客户，get/post就严格区分开来了。<br /><br />method_dispatch现在是直接实现在ApplicationController中的，代码如下：<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">class ApplicationController </span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);"> ActionController</span><span style="color: rgb(0, 0, 0);">::</span><span style="color: rgb(0, 0, 0);">Base<br />  protected<br />  def self</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 0);">method_dispatch(</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">methods)<br />    before_filter </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">do_method_dispatch</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">only </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> methods</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 0);">flatten</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 255);">map</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">&amp;:</span><span style="color: rgb(0, 0, 0);">to_sym)<br />  end<br /><br />  private<br />  def do_method_dispatch<br />    </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> request</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 0);">post</span><span style="color: rgb(0, 0, 0);">?</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">&amp;&amp;</span><span style="color: rgb(0, 0, 0);"> respond_to</span><span style="color: rgb(0, 0, 0);">?</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0); font-weight: bold;">"</span><span style="color: rgb(0, 0, 0); font-weight: bold;">#{action_name}_post</span><span style="color: rgb(0, 0, 0); font-weight: bold;">"</span><span style="color: rgb(0, 0, 0);">)<br />      </span><span style="color: rgb(0, 0, 255);">eval</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0); font-weight: bold;">"</span><span style="color: rgb(0, 0, 0); font-weight: bold;">#{action_name}_post</span><span style="color: rgb(0, 0, 0); font-weight: bold;">"</span><span style="color: rgb(0, 0, 0);">)<br />      </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> false<br />    end<br />  end<br />end</span></div><br />由于ApplicationController里面的方法会被子类继承到，所以必须严格处理访问级别。<br /><br />使用如下：<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">class TestController </span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);"> ApplicationController<br />  method_dispatch </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">a<br /><br />  def </span><span style="color: rgb(0, 0, 255);">index</span><span style="color: rgb(0, 0, 0);"><br />  end<br /><br />  def a<br />    render </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">text </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0); font-weight: bold;">get a</span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0);"><br />  end<br />  def b<br />    render </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">text </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0); font-weight: bold;">get b</span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0);"><br />  end<br />  protected<br />  def a_post<br />    render </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">text </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0); font-weight: bold;">post a</span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0);"><br />  end<br />  def b_post<br />    render </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">text </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0); font-weight: bold;">post b</span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0);"><br />  end<br />end</span></div><br />注意a_post，b_post要被保护起来防止直接调用。<br /><br />index.rhtml里面演示了使用get和post的情况：<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">&lt;%=</span><span style="color: rgb(0, 0, 0);"> link_to </span><span style="color: rgb(0, 0, 0); font-weight: bold;">"</span><span style="color: rgb(0, 0, 0); font-weight: bold;">Get a</span><span style="color: rgb(0, 0, 0); font-weight: bold;">"</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">action </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0); font-weight: bold;">a</span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">%&gt;</span><span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 0, 0);">&lt;%=</span><span style="color: rgb(0, 0, 0);"> link_to </span><span style="color: rgb(0, 0, 0); font-weight: bold;">"</span><span style="color: rgb(0, 0, 0); font-weight: bold;">Post a</span><span style="color: rgb(0, 0, 0); font-weight: bold;">"</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"> {</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">action </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0); font-weight: bold;">a</span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0);">}</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"> {</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">post </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> true} </span><span style="color: rgb(0, 0, 0);">%&gt;&lt;</span><span style="color: rgb(0, 0, 0);">br </span><span style="color: rgb(0, 0, 0);">/&gt;</span><span style="color: rgb(0, 0, 0);"><br /><br /></span><span style="color: rgb(0, 0, 0);">&lt;%=</span><span style="color: rgb(0, 0, 0);"> link_to </span><span style="color: rgb(0, 0, 0); font-weight: bold;">"</span><span style="color: rgb(0, 0, 0); font-weight: bold;">Get b</span><span style="color: rgb(0, 0, 0); font-weight: bold;">"</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">action </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0); font-weight: bold;">b</span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">%&gt;</span><span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 0, 0);">&lt;%=</span><span style="color: rgb(0, 0, 0);"> link_to </span><span style="color: rgb(0, 0, 0); font-weight: bold;">"</span><span style="color: rgb(0, 0, 0); font-weight: bold;">Post b</span><span style="color: rgb(0, 0, 0); font-weight: bold;">"</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"> {</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">action </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0); font-weight: bold;">b</span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0);">}</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"> {</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">post </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> true} </span><span style="color: rgb(0, 0, 0);">%&gt;&lt;</span><span style="color: rgb(0, 0, 0);">br </span><span style="color: rgb(0, 0, 0);">/&gt;</span></div><br />rails在处理有:post =&gt; true参数的link_to时，生成的代码如下：<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">a </span><span style="color: rgb(255, 0, 0);">href</span><span style="color: rgb(0, 0, 255);">="/test/a"</span><span style="color: rgb(255, 0, 0);"> onclick</span><span style="color: rgb(0, 0, 255);">="var f = document.createElement('form'); <br />       this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href; f.submit();return false;"</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);">Post a</span><span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">a</span><span style="color: rgb(0, 0, 255);">&gt;</span></div><br />经测试上面代码工作情况良好，使用get访问/test/a时，显示get a；使用post访问时，显示post a。使用get访问/test/b时，显示get b；使用post时，显示get b，因为b并没有使用method_dispatch。<br /><br /><b>三、应用</b><br /><br />下面的posts_controller.rb是scaffold生成的：<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">class PostsController </span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);"> ApplicationController<br />  def </span><span style="color: rgb(0, 0, 255);">index</span><span style="color: rgb(0, 0, 0);"><br />    list<br />    render </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">action </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0); font-weight: bold;">list</span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0);"><br />  end<br /><br />  </span><span style="color: rgb(0, 128, 0);">#</span><span style="color: rgb(0, 128, 0);"> GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">  verify </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">method </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">post</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">only </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> [ </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">destroy</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">create</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">update ]</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"><br />         </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">redirect_to </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> { </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">action </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">list }<br /><br />  def list<br />    </span><span style="color: rgb(128, 0, 128);">@post_pages</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 128);">@posts</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> paginate </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">posts</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">per_page </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 0);">10</span><span style="color: rgb(0, 0, 0);"><br />  end<br /><br />  def show<br />    </span><span style="color: rgb(128, 0, 128);">@post</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> Post</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 0);">find(params[</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">id])<br />  end<br /><br />  def new<br />    </span><span style="color: rgb(128, 0, 128);">@post</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> Post</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 0);">new<br />  end<br /><br />  def create<br />    </span><span style="color: rgb(128, 0, 128);">@post</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> Post</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 0);">new(params[</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">post])<br />    </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 128);">@post</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 0);">save<br />      flash[</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">notice] </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0); font-weight: bold;">Post was successfully created.</span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0);"><br />      redirect_to </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">action </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0); font-weight: bold;">list</span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0);"><br />    </span><span style="color: rgb(0, 0, 255);">else</span><span style="color: rgb(0, 0, 0);"><br />      render </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">action </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0); font-weight: bold;">new</span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0);"><br />    end<br />  end<br /><br />  def edit<br />    </span><span style="color: rgb(128, 0, 128);">@post</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> Post</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 0);">find(params[</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">id])<br />  end<br /><br />  def update<br />    </span><span style="color: rgb(128, 0, 128);">@post</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> Post</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 0);">find(params[</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">id])<br />    </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 128);">@post</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 0);">update_attributes(params[</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">post])<br />      flash[</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">notice] </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0); font-weight: bold;">Post was successfully updated.</span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0);"><br />      redirect_to </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">action </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0); font-weight: bold;">show</span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">id </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 128);">@post</span><span style="color: rgb(0, 0, 0);"><br />    </span><span style="color: rgb(0, 0, 255);">else</span><span style="color: rgb(0, 0, 0);"><br />      render </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">action </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0); font-weight: bold;">edit</span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0);"><br />    end<br />  end<br /><br />  def destroy<br />    Post</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 0);">find(params[</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">id])</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 0);">destroy<br />    redirect_to </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">action </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0); font-weight: bold;">list</span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0);"><br />  end<br />end</span></div><br />可以看到，它添加了verify，但action过多，需要在verify中维护一份对应方法名，稍不留神就容易出现漏洞。<br /><br />我把它修改如下：<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">class PostsController </span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);"> ApplicationController<br />  method_dispatch </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">new</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">edit</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">destroy<br /><br />  def </span><span style="color: rgb(0, 0, 255);">index</span><span style="color: rgb(0, 0, 0);"><br />    list<br />    render </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">action </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0); font-weight: bold;">list</span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0);"><br />  end<br /><br />  def list<br />    </span><span style="color: rgb(128, 0, 128);">@post_pages</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 128);">@posts</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> paginate </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">posts</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">per_page </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 0);">10</span><span style="color: rgb(0, 0, 0);"><br />  end<br /><br />  def show<br />    </span><span style="color: rgb(128, 0, 128);">@post</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> Post</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 0);">find(params[</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">id])<br />  end<br /><br />  def new<br />    </span><span style="color: rgb(128, 0, 128);">@post</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> Post</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 0);">new<br />  end<br /><br />  def edit<br />    </span><span style="color: rgb(128, 0, 128);">@post</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> Post</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 0);">find(params[</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">id])<br />  end<br /><br />  def destroy<br />    render </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">inline </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">&lt;&lt;-</span><span style="color: rgb(0, 0, 0);">EOS<br />      Are you sure?<br />      </span><span style="color: rgb(0, 0, 0);">&lt;%=</span><span style="color: rgb(0, 0, 0);"> link_to </span><span style="color: rgb(0, 0, 0); font-weight: bold;">"</span><span style="color: rgb(0, 0, 0); font-weight: bold;">Yes</span><span style="color: rgb(0, 0, 0); font-weight: bold;">"</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"> {}</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">post </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> true </span><span style="color: rgb(0, 0, 0);">%&gt;</span><span style="color: rgb(0, 0, 0);"><br />      </span><span style="color: rgb(0, 0, 0);">&lt;%=</span><span style="color: rgb(0, 0, 0);"> link_to </span><span style="color: rgb(0, 0, 0); font-weight: bold;">"</span><span style="color: rgb(0, 0, 0); font-weight: bold;">No</span><span style="color: rgb(0, 0, 0); font-weight: bold;">"</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">action </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0); font-weight: bold;">edit</span><span style="color: rgb(0, 0, 0); font-weight: bold;">', :id =&gt; params[:id]</span><span style="color: rgb(0, 0, 0);"></span><span style="color: rgb(0, 0, 0);">%&gt;</span><span style="color: rgb(0, 0, 0);"><br />    EOS<br />  end<br /><br />  protected<br />  def destroy_post<br />    Post</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 0);">find(params[</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">id])</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 0);">destroy<br />    redirect_to </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">action </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0); font-weight: bold;">list</span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0);"><br />  end<br />  def edit_post<br />    </span><span style="color: rgb(128, 0, 128);">@post</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> Post</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 0);">find(params[</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">id])<br />    </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 128);">@post</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 0);">update_attributes(params[</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">post])<br />      flash[</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">notice] </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0); font-weight: bold;">Post was successfully updated.</span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0);"><br />      redirect_to </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">action </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0); font-weight: bold;">show</span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">id </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 128);">@post</span><span style="color: rgb(0, 0, 0);"><br />    </span><span style="color: rgb(0, 0, 255);">else</span><span style="color: rgb(0, 0, 0);"><br />      render </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">action </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0); font-weight: bold;">edit</span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0);"><br />    end<br />  end<br />  def new_post<br />    </span><span style="color: rgb(128, 0, 128);">@post</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> Post</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 0);">new(params[</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">post])<br />    </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 128);">@post</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 0);">save<br />      flash[</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">notice] </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0); font-weight: bold;">Post was successfully created.</span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0);"><br />      redirect_to </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">action </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0); font-weight: bold;">list</span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0);"><br />    </span><span style="color: rgb(0, 0, 255);">else</span><span style="color: rgb(0, 0, 0);"><br />      render </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">action </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0); font-weight: bold;">new</span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0);"><br />    end<br />  end<br />end</span></div><br />相应地，还需要把new.rhtml中的action从create修改到new，把edit.rhtml中的action从update修改到edit。<br /><br />这样的修改把必须使用post请求的action隐藏起来，而相应的get操作是不修改或删除记录的，如果以post请求，才会自动调用这些保护的方法。<br /><img src ="http://www.cppblog.com/cpunion/aggbug/12571.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2006-09-17 11:13 <a href="http://www.cppblog.com/cpunion/archive/2006/09/17/12571.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[Ruby] Ruby AOP</title><link>http://www.cppblog.com/cpunion/archive/2006/09/16/12539.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Sat, 16 Sep 2006 01:46:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2006/09/16/12539.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/12539.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2006/09/16/12539.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/12539.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/12539.html</trackback:ping><description><![CDATA[昨天在答一个问题时，看题不清答错了，不过却让我花了点时间想如何实现简单的AOP。<br /><br />在其它语言里实现AOP的确比较麻烦，java要用到动态proxy，如果是C＋＋，除了从源码上修改还真没好办法，aspectc就是这么做的。那么ruby里面如何实现呢？<br /><br />由于ruby是动态脚本语言，运行期可以把一个方法改名，也可以构造一个字符串动态生成方法，那么实现这个就不是难事了。<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">module ExecuteBefore<br />  def self</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 0);">included(base)<br />    base</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 0);">extend(ClassMethods)<br />  end<br /><br />  module ClassMethods<br />    def execute_before(before_method</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">methods)<br />      methods</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 0);">flatten</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 255);">map</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">&amp;:</span><span style="color: rgb(0, 0, 0);">to_sym)</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 255);">each</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">do</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);">method</span><span style="color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"><br />        alias_method </span><span style="color: rgb(0, 0, 0); font-weight: bold;">"</span><span style="color: rgb(0, 0, 0); font-weight: bold;">#{method}_old</span><span style="color: rgb(0, 0, 0); font-weight: bold;">"</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 0);">to_sym</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"> method<br />        class_eval </span><span style="color: rgb(0, 0, 0);">&lt;&lt;-</span><span style="color: rgb(0, 0, 0);">eval_end<br />          def </span><span style="color: rgb(0, 128, 0);">#</span><span style="color: rgb(0, 128, 0);">{method}(*args)<br />            #{before_method}(*args)<br />            #{method}_old(*args)</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">          end<br />        eval_end<br />      end<br />    end<br />  end<br />end<br /></span></div><br />使用时只需要在类里面include这个模块就行了，相当于mixin的功能。<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">class TestController </span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);"> ApplicationController<br /><br />  def </span><span style="color: rgb(0, 0, 255);">index</span><span style="color: rgb(0, 0, 0);"><br />    a(</span><span style="color: rgb(128, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">)<br />    b(</span><span style="color: rgb(128, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(128, 0, 0);">2</span><span style="color: rgb(0, 0, 0);">)<br />    c(</span><span style="color: rgb(128, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(128, 0, 0);">2</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(128, 0, 0);">3</span><span style="color: rgb(0, 0, 0);">)<br />    render </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">text </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0); font-weight: bold;">hello</span><span style="color: rgb(0, 0, 0); font-weight: bold;">'</span><span style="color: rgb(0, 0, 0);"><br />  end<br /><br />  protected<br />  def </span><span style="color: rgb(0, 0, 255);">log</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">args)<br />    puts </span><span style="color: rgb(0, 0, 0); font-weight: bold;">"</span><span style="color: rgb(0, 0, 0); font-weight: bold;">log: #{args.map(&amp;:to_s).join(', ')}</span><span style="color: rgb(0, 0, 0); font-weight: bold;">"</span><span style="color: rgb(0, 0, 0);"><br />  end<br /><br />  def a(a)<br />  end<br /><br />  def b(a</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">b)<br />  end<br /><br />  def c(a</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">b</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">c)<br />  end<br /><br />  include ExecuteBefore<br />  execute_before </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 255);">log</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">a</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">b</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">c<br />end</span></div><br />注意，由于使用execute_before时后面几个方法必须要有定义，所以必须放在后面，否则就会出错。<br /><img src ="http://www.cppblog.com/cpunion/aggbug/12539.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2006-09-16 09:46 <a href="http://www.cppblog.com/cpunion/archive/2006/09/16/12539.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[RoR] Rails unittest一个小bug</title><link>http://www.cppblog.com/cpunion/archive/2006/09/16/12536.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Sat, 16 Sep 2006 01:32:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2006/09/16/12536.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/12536.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2006/09/16/12536.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/12536.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/12536.html</trackback:ping><description><![CDATA[之前为了省事，数据库配置如下：<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">development_pgsql</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);"><br />  adapter</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);"> postgresql<br />  database</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);"> myproject_development<br />  username</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);"> postgres<br />  password</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);"> <br /><br />development_mysql</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);"><br />  adapter</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);"> mysql<br />  database</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);"> myproject_development<br />  username</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);"> root<br />  password</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);"> <br /><br />development</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);"><br />  development_mysql<br /><br />test</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);"><br />  adapter</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);"> postgresql<br />  database</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);"> myproject_test<br />  username</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);"> postgres<br />  password</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);"> <br /><br />production</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);"><br />  development</span></div><br />正常运行没什么问题。后来发现在运行rake test作单元测试时会报错，把拷贝过来就没有问题。不过rubyonrails.com上不允许匿名提交bug，还真麻烦。<br /><br />另外发现config.active_record.schema_format = :ruby配置下，postgresql的timestamp字段默认值current_timestamp不能正确复制到数据库。经检查它是使用db:schema:dump复制下数据库模式，再使用db:schema:load生成测试数据库模式的，这个模块为了各数据库统一，会去掉那些不一致的默认值。解决办法是设置config.active_record.schema_format = :sql。<img src ="http://www.cppblog.com/cpunion/aggbug/12536.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2006-09-16 09:32 <a href="http://www.cppblog.com/cpunion/archive/2006/09/16/12536.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[RoR] 修复update_attribute(s)更新全部字段的问题</title><link>http://www.cppblog.com/cpunion/archive/2006/08/26/11712.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Fri, 25 Aug 2006 18:10:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2006/08/26/11712.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/11712.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2006/08/26/11712.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/11712.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/11712.html</trackback:ping><description><![CDATA[<span class="postbody">这是前段时间有人讨论过的问题： <br /></span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed">
												<b>代码:</b>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">
										<br />order = Order.find(1) <br />order.update_attribute(:status, 'finished') <br /></td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<br />假定orders表有10个字段，你只想更新其中一个，但active record会生成一个更新全部字段的SQL语句，假定其中一个字段值长度是20K，这个负担可能会有些重。 <br /><br />我尝试解决这个问题，写了个简单的插件： <br /></span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed">
												<b>代码:</b>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">
										<br />module ActiveRecord <br />  class Base <br />    def update_attribute(name, value) <br />      update_attributes(name =&gt; value) <br />    end <br /><br />    def update_attributes(new_attributes) <br />      return if new_attributes.nil? <br />      attributes = new_attributes.dup <br />      attributes.stringify_keys! <br />      self.attributes = attributes <br />      update(attributes) <br />    end <br /><br />    private <br />      def update(attrs = nil) <br />        connection.update( <br />          "UPDATE #{self.class.table_name} " + <br />          "SET #{quoted_comma_pair_list(connection, attributes_with_quotes(false, attrs))} " + <br />          "WHERE #{self.class.primary_key} = #{quote(id)}", <br />          "#{self.class.name} Update" <br />        ) <br />        <br />        return true <br />      end <br /><br />      def attributes_with_quotes(include_primary_key = true, attrs = nil) <br />        (attrs || attributes).inject({}) do |quoted, (name, value)| <br />          if column = column_for_attribute(name) <br />            quoted[name] = quote(value, column) unless !include_primary_key &amp;&amp; column.primary <br />          end <br />          quoted <br />        end <br />      end <br />  end <br />end <br /></td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<p>
						<br />attributes_with_quotes函数的参数搞这么复杂，原因是我想即便是用这段代码替换库里面的部分，也不影响原有代码的正常功能。 <br /><br />可以简单测试一下上面的例子，它生成的SQL语句会简洁很多，大概是这样子： <br />UPDATE orders SET "status" = 'finished' WHERE id = 1<br /><br /><strong>已发现的BUG和修复：<br /></strong><br /><strong>1、没有调用validation (by cookoo)。</strong>由于原有代码调用save，而save被覆盖成有验证的代码，所以具有验证功能。解决办法是增加一段代码：</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">
						<span style="COLOR: #000000">module ActiveRecord<br />  module ValidationsFix<br />    </span>
						<span style="COLOR: #0000ff">def</span>
						<span style="COLOR: #000000"> self.append_features(base) </span>
						<span style="COLOR: #008000">#</span>
						<span style="COLOR: #008000"> :nodoc:</span>
						<span style="COLOR: #008000">
								<br />
						</span>
						<span style="COLOR: #000000">      super<br />      base.class_eval do<br />        alias_method :update_attributes_without_validation, :update_attributes<br />        alias_method :update_attributes, :update_attributes_with_validation<br />      end<br />    end<br /><br />    </span>
						<span style="COLOR: #0000ff">def</span>
						<span style="COLOR: #000000"> update_attributes_with_validation(new_attributes)<br />      </span>
						<span style="COLOR: #0000ff">return</span>
						<span style="COLOR: #000000"> </span>
						<span style="COLOR: #0000ff">if</span>
						<span style="COLOR: #000000"> new_attributes.nil?<br />      attributes = new_attributes.dup<br />      attributes.stringify_keys!<br />      self.attributes </span>
						<span style="COLOR: #000000">=</span>
						<span style="COLOR: #000000"> attributes<br /><br />      </span>
						<span style="COLOR: #0000ff">if</span>
						<span style="COLOR: #000000"> valid?<br />        update_attributes_without_validation(attributes)<br />      </span>
						<span style="COLOR: #0000ff">else</span>
						<span style="COLOR: #000000">
								<br />        </span>
						<span style="COLOR: #0000ff">return</span>
						<span style="COLOR: #000000"> false<br />      end<br />    end<br />  end<br />end<br /><br />ActiveRecord::Base.class_eval do<br />  include ActiveRecord::ValidationsFix<br />end</span>
				</div>
				<p>简单测试通过。</p>
		</span><img src ="http://www.cppblog.com/cpunion/aggbug/11712.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2006-08-26 02:10 <a href="http://www.cppblog.com/cpunion/archive/2006/08/26/11712.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[ROR] &amp;:id这种用法</title><link>http://www.cppblog.com/cpunion/archive/2006/07/11/9688.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Tue, 11 Jul 2006 07:40:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2006/07/11/9688.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/9688.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2006/07/11/9688.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/9688.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/9688.html</trackback:ping><description><![CDATA[这是ActiveSupport扩展的一个方法。原代码如下：<br /><br />class Symbol<br />  def to_proc<br />    Proc.new { |*args| args.shift.__send__(self, *args) }<br />  end<br />end<br /><br />它扩展出这种用法：<br /><br />(1..5).map(&amp;:to_s)<br /><br />map原本是要接受一个block参数，普通的用法是：<br /><br />(1..5).map{|e| e.to_s}<br /><br />或者：<br /><br />proc = Proc.new{|e| e.to_s}<br />(1..5).map(&amp;proc)<br /><br />上面这个(1..5).map(&amp;:to_s)用法可以拆成3步来解释：<br />sym = :to_s<br />proc = Proc.new{|*args| args.shift.send(sym, *args)}<br />(1..5).map(&amp;proc)<br /><br />有个疑问，经过yanping.jia解释，map(&amp;:to_s)因为出现了&amp;符号，所以:to_s会执行to_proc方法，然后与&amp;一起合成&amp;proc交给map处理。虽然说得通，不过我总觉得这个解释中，&amp;这个符号做了2次工作，是否合理？<br /><br />这种用法原本是Ruby Extensions Project发明的，在RoR中作了点修改。原来的版本是：<br /><br />class Symbol<br />    def to_proc<br />      proc { |obj, *args| obj.send(self, *args) }<br />    end<br />end<br /><br />它使用2个参数来分出一个参数，而RoR版本则使用shift分出来。<br /><br /><br />刚才又想了一下，yanping.jia的解释应该是合理的，解释器看到&amp;:id时，先会判断是否是一个方法调用，如果是则需要把:id转成一个proc。否则就是语法错误了。<img src ="http://www.cppblog.com/cpunion/aggbug/9688.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2006-07-11 15:40 <a href="http://www.cppblog.com/cpunion/archive/2006/07/11/9688.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[ROR] 修复“使用POST方法时,通过URL参数改写_session_id无效”的问题</title><link>http://www.cppblog.com/cpunion/archive/2006/07/03/9346.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Mon, 03 Jul 2006 15:58:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2006/07/03/9346.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/9346.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2006/07/03/9346.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/9346.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/9346.html</trackback:ping><description><![CDATA[问题：<br /><br />

使用Flash 8提供的FileReference可以方便地一次选择多个文件上传，不过除了在IE上以外，其它浏览器上的都会出现Cookie与浏览器不一致的问题。<br /><br />

解决办法：

直接的做法就是在上传时，附加一个session_id在URL上，在服务端处理时使用这个Session。<br /><br />


在Rails中，可以把_session_id=xxxx附加在URL上。不过测试的结果是，附加的session_id只有在GET请求时才正常，POST请示时会被忽略。<br /><br />


知道了这一点，只需要寻找GET和POST请求处理的差别。也费了一番周折，才发现问题出在actionpack/lib/action_controller/cgi_ext/raw_post_data_fix.rb里。<br /><br />


只需要在POST时也处理一下URL参数即可。由于它是通过read_query_params方法来分开处理的，所以要在POST请求时，调用一下read_query_params(:get)，并把结果合并。代码如下：<br /><br />


@params.merge!(CGI.parse(read_query_params(:get))) if method == :post || method == :put<br /><br />


这行加到initialize_query方法尾部即可。由于原来的方法可能返回了@params，所以也加一行@params在结尾，以免造成不必要的麻烦。<img src ="http://www.cppblog.com/cpunion/aggbug/9346.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2006-07-03 23:58 <a href="http://www.cppblog.com/cpunion/archive/2006/07/03/9346.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[RoR] 实现一个auto_redirect_to</title><link>http://www.cppblog.com/cpunion/archive/2006/05/20/7434.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Fri, 19 May 2006 18:33:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2006/05/20/7434.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/7434.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2006/05/20/7434.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/7434.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/7434.html</trackback:ping><description><![CDATA[最近在使用RoR做项目，体会到了快速开发的乐趣，也遇到了一些困难，其中一个就是redirect_to。<br /><br />我遇到的一个问题是，当使用Ajax更新页面局部内容时，session内容已经过期，这时需要整个页面跳转到登录页面。<br /><br />直接调用redirect_to会使局部内容显示成登录页面，它是在HTTP头里写入重定向参数来实现的。在我这里的特殊情况下，正确的做法是让它执行一个包含在&lt;script&gt;标记中的脚本，在脚本中更改窗口location值来跳转。<br /><br />不过RoR中使用Ajax时，会根据:update参数来决定是使用Updater还是Request。如果使用Updater方式，则应返回一段纯脚本；如果是Request方式，应返回一段包括在&lt;script&gt;标记中的脚本；如果是普通方式，就应该使用原有的redirect_to函数了。因为服务端无法区分使用的是哪种方式来请求，所以简单的做法是每个请求都附加一个参数用来区分，不加参数则是普通请求方式。<br /><br />为了达到这个目的，我修改了prototype_helper中的remote_function函数。这个函数根据传递进来的参数来决定使用Request或是Updater，我就在这里下手：<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">      def remote_function(options)<br />        javascript_options </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> options_for_ajax(options)<br /><br />        update </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">''</span><span style="color: rgb(0, 0, 0);"><br />        </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> options[:update] and options[:update].is_a</span><span style="color: rgb(0, 0, 0);">?</span><span style="color: rgb(0, 0, 0);">Hash<br />          update  </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> []<br />          update </span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">success:'#{options[:update][:success]}'</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> options[:update][:success]<br />          update </span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">failure:'#{options[:update][:failure]}'</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> options[:update][:failure]<br />          update  </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> update.join(</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">) </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">}</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"><br />        elsif options[:update]<br />          update </span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">'#{options[:update]}'</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"><br />        end<br /><br />        function </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> update.empty</span><span style="color: rgb(0, 0, 0);">?</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">?</span><span style="color: rgb(0, 0, 0);"> <br />          </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">new Ajax.Request(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> :<br />          </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">new Ajax.Updater(#{update}, </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"><br />    <br />        url_options </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> options[:url]<br /><font color="#ff0000"><b>        ajax_options </b></font></span><font color="#ff0000"><b><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> options[:update] </span><span style="color: rgb(0, 0, 0);">?</span><span style="color: rgb(0, 0, 0);"> {:ajax </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">update</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">} : {:ajax </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">request</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">}<br />        url_options </span><span style="color: rgb(0, 0, 0);">=</span></b></font><span style="color: rgb(0, 0, 0);"><font color="#ff0000"><b> url_options.merge(ajax_options)</b></font><br />        url_options </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> url_options.merge(:escape </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">false</span><span style="color: rgb(0, 0, 0);">) </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> url_options.is_a</span><span style="color: rgb(0, 0, 0);">?</span><span style="color: rgb(0, 0, 0);"> Hash<br />        function </span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">'#{url_for(url_options)}'</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"><br />        function </span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, #{javascript_options})</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"><br /><br />        function </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">#{options[:before]}; #{function}</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> options[:before]<br />        function </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">#{function}; #{options[:after]}</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">  </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> options[:after]<br />        function </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">if (#{options[:condition]}) { #{function}; }</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> options[:condition]<br />        function </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">if (confirm('#{escape_javascript(options[:confirm])}')) { #{function}; }</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> options[:confirm]<br /><br />        </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> function<br />      end</span></div><br />有红色的2行是我添加的，由于这个编辑器的原因，没有显示成整行红色。这2行的作用是判断是否有:update参数，用它来决定是添加ajax=update还是ajax=request。<br /><br />现在可以实现一个简单的auto_redirect_to了：<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">  def auto_redirect_to(method, url)<br />    </span><span style="color: rgb(0, 0, 255);">case</span><span style="color: rgb(0, 0, 0);"> method<br />    when </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">request</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"><br />      request_redirect_to(url)<br />    when </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">update</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"><br />      update_redirect_to(url)<br />    </span><span style="color: rgb(0, 0, 255);">else</span><span style="color: rgb(0, 0, 0);"><br />      redirect_to(url)<br />    end<br />  end<br />  <br />  def request_redirect_to(url)<br />    render :update </span><span style="color: rgb(0, 0, 255);">do</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);">page</span><span style="color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"><br />      page.redirect_to(url)<br />    end<br />  end<br />  <br />  def update_redirect_to(url)<br />    render :inline </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">&lt;&lt;-</span><span style="color: rgb(0, 0, 0);">EOS<br />      </span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">script language</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">javascript</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />      </span><span style="color: rgb(0, 0, 0);">&lt;%=</span><span style="color: rgb(0, 0, 0);"><br />        render :update </span><span style="color: rgb(0, 0, 255);">do</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);">page</span><span style="color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"><br />          page.redirect_to(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">#{url_for(url)}</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br />        end<br />      </span><span style="color: rgb(0, 0, 0);">%&gt;</span><span style="color: rgb(0, 0, 0);"><br />      </span><span style="color: rgb(0, 0, 0);">&lt;/</span><span style="color: rgb(0, 0, 0);">script</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />    EOS<br />  end</span></div><br />使用helper方式使它能够被include到ApplicationController中就行了。<br /><br />为了不和参数绑得太死，这里把method作为参数由调用者传入。<br /><br />使用方法，以Login Engine为例，它在access_denied中处理跳转。在ApplicationController中重写这个函数：<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">    def access_denied<br />      auto_redirect_to(</span><span style="color: rgb(0, 0, 255);">params</span><span style="color: rgb(0, 0, 0);">[:ajax], :controller </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">/user</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, :action </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">login</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br />      </span><span style="color: rgb(0, 0, 255);">false</span><span style="color: rgb(0, 0, 0);"><br />    end  </span></div><br />现在可以测试了。请求可以是普通的（超链接），Updater方式（请求到一个DIV里），Request方式，现在都能够跳转到正确页面。<br /><br />ajax参数通过hack库代码来实现，对于使用者来说基本上是透明的。<br /><img src ="http://www.cppblog.com/cpunion/aggbug/7434.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2006-05-20 02:33 <a href="http://www.cppblog.com/cpunion/archive/2006/05/20/7434.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[RoR] 在RoR中调用.Net webservice</title><link>http://www.cppblog.com/cpunion/archive/2006/05/14/7138.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Sun, 14 May 2006 12:08:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2006/05/14/7138.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/7138.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2006/05/14/7138.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/7138.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/7138.html</trackback:ping><description><![CDATA[首先写一个简单的webservice：<br /><br /><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"><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000"> System;<br /></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000"> System.Web;<br /></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000"> System.Web.Services;<br /></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000"> System.Web.Services.Protocols;<br /><br />[WebService(Namespace </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">http://tempuri.org/</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)]<br />[WebServiceBinding(ConformsTo </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> WsiProfiles.BasicProfile1_1)]<br /></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> Service : System.Web.Services.WebService<br />{<br />    [WebMethod]<br />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000"> HelloWorld(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000"> name) {<br />        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Hello, </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> name;<br />    }<br />    <br />}</span></div><br />在RoR项目里，添加app/apis/test_api.rb：<br /><br /><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"><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> TestApi </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000"> ActionWebService::API::Base<br />  api_method :HelloWorld, :expects </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> [{:name </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> :string}], :returns </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> [:string]<br />end<br /></span></div><br />这是RoR里面通用的webservice元信息描述。<br /><br />添加app/controllers/test_controller.rb:<br /><br /><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"><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> TestController </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000"> ApplicationController<br />  web_client_api :test, :soap, </span><span style="COLOR: #800000">"</span><span style="COLOR: #800000">http://localhost/test/Service.asmx</span><span style="COLOR: #800000">"</span><span style="COLOR: #000000">, <br />                 :namespace </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> </span><span style="COLOR: #800000">"</span><span style="COLOR: #800000">http://tempuri.org/</span><span style="COLOR: #800000">"</span><span style="COLOR: #000000">,<br />                 :soap_action_base </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> </span><span style="COLOR: #800000">"</span><span style="COLOR: #800000">http://tempuri.org</span><span style="COLOR: #800000">"</span><span style="COLOR: #000000">,<br />                 :driver_options</span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000">{:default_encodingstyle </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> SOAP::EncodingStyle::ASPDotNetHandler::Namespace }<br /><br />  </span><span style="COLOR: #0000ff">def</span><span style="COLOR: #000000"> hello<br />    render_text test.HelloWorld(</span><span style="COLOR: #800000">"</span><span style="COLOR: #800000">Li Jie</span><span style="COLOR: #800000">"</span><span style="COLOR: #000000">)<br />  end<br />end</span></div><br />:soap_action_base选项是一个修补，不加这个选项会产生SOAPAction头错误。<br /><br />运行服务器，在浏览器中访问/test/hello，发现名字为空。经过长时间调试，发现.Net在解析SOAP消息体时，不能处理这种命名空间：<br /><br /><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"><span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">n1:HelloWorld </span><span style="COLOR: #ff0000">xmlns:n1</span><span style="COLOR: #0000ff">="http://tempuri.org/"</span><span style="COLOR: #ff0000"><br />        soap:encodingStyle</span><span style="COLOR: #0000ff">="http://schemas.xmlsoap.org/soap/encoding/"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br />      </span><span style="COLOR: #0000ff">&lt;name</span><span style="COLOR: #800000"> </span><span style="COLOR: #ff0000">xsi:type</span><span style="COLOR: #0000ff">="xsd:string"</span><span style="COLOR: #0000ff">&gt;Li Jie</span><span style="COLOR: #0000ff">&lt;/name</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br />    </span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">n1:HelloWorld</span><span style="COLOR: #0000ff">&gt;</span></div><br />把n1去掉就行了。不过这部分实现在rubylib/soap/rpc/proxy.rb里面，实在不方便修改。为了让这个测试通过，暂时做了点小修改：<br /><br /><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"><span style="COLOR: #000000">  </span><span style="COLOR: #0000ff">def</span><span style="COLOR: #000000"> route(req_header, req_body, reqopt, resopt)<br />    req_env </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> ::SOAP::SOAPEnvelope.new(req_header, req_body)<br />    unless reqopt[:envelopenamespace].nil?<br />      set_envelopenamespace(req_env, reqopt[:envelopenamespace])<br />    end<br />    reqopt[:external_content] </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> nil<br />    conn_data </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> marshal(req_env, reqopt)<br />    </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ext </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> reqopt[:external_content]<br />      mime </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> MIMEMessage.new<br />      ext.each do </span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">k, v</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000"><br />          mime.add_attachment(v.data)<br />      end<br />      mime.add_part(conn_data.send_string </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> </span><span style="COLOR: #800000">"</span><span style="COLOR: #800000">\r\n</span><span style="COLOR: #800000">"</span><span style="COLOR: #000000">)<br />      mime.close<br />      conn_data.send_string </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> mime.content_str<br />      conn_data.send_contenttype </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> mime.headers[</span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">content-type</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">].str<br />    end<br /><br /><strong>    conn_data.send_string.gsub!(</strong></span><strong><span style="COLOR: #000000">/</span><span style="COLOR: #000000">:n1</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">, </span><span style="COLOR: #800000">''</span></strong><strong><span style="COLOR: #000000">)<br />    conn_data.send_string.gsub!(</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">n1:</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">, </span><span style="COLOR: #800000">''</span></strong><span style="COLOR: #000000"><strong>)</strong><br /><br />    conn_data </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> @streamhandler.send(@endpoint_url, conn_data,<br />      reqopt[:soapaction])<br />    </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> conn_data.receive_string.empty?<br />      </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> nil<br />    end<br />    unmarshal(conn_data, resopt)<br />  end</span></div><br />加粗的2行是我添加的代码，勉强可以让它工作，不过显然不是正确的方法。<br /><br />不知道是不是.Net库里面的BUG。<img src ="http://www.cppblog.com/cpunion/aggbug/7138.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2006-05-14 20:08 <a href="http://www.cppblog.com/cpunion/archive/2006/05/14/7138.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[RoR] 脚本模拟RJS刷新页面</title><link>http://www.cppblog.com/cpunion/archive/2006/05/13/7087.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Sat, 13 May 2006 15:49:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2006/05/13/7087.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/7087.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2006/05/13/7087.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/7087.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/7087.html</trackback:ping><description><![CDATA[使用脚本来模拟RJS语法及功能。<br /><br />演示页面直接在浏览器中观看。<br /><br /><a href="/Files/cpunion/script_action_demo.zip">演示下载</a><img src ="http://www.cppblog.com/cpunion/aggbug/7087.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2006-05-13 23:49 <a href="http://www.cppblog.com/cpunion/archive/2006/05/13/7087.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[RoR] 用javascript脚本模拟一个action</title><link>http://www.cppblog.com/cpunion/archive/2006/05/12/7046.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Fri, 12 May 2006 15:41:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2006/05/12/7046.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/7046.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2006/05/12/7046.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/7046.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/7046.html</trackback:ping><description><![CDATA[rails 1.1以上版本提供了强大优雅的RJS，可能执行一个请求多个更新。<br /><br />有些时候我们并不需要请求服务器，只想在浏览器上执行某些脚本更新，但又想使用RJS。所以为RoR增加了这项功能。<br /><br />使用方法：<br /><br /><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"><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">script language</span><span style="COLOR: #000000">=</span><span style="COLOR: #800000">"</span><span style="COLOR: #800000">javascript</span><span style="COLOR: #800000">"</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #000000">&lt;%=</span><span style="COLOR: #000000"> <br />render :update do </span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">page</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000"><br />  page.define_action </span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">test_action</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000"> do<br />    page.call_script </span><span style="COLOR: #000000">&lt;&lt;-</span><span style="COLOR: #000000">EOS<br />      alert(params.comment.title);<br />      alert(params.comment.body);<br />    EOS<br />    page.replace_html </span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">errors</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">, </span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">ERROR</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000"><br />  end<br /><br />  page.define_action </span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">link_action</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000"> do<br />    page.replace_html </span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">errors</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">, </span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">ERROR</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000"><br />  end<br />end<br /></span><span style="COLOR: #000000">%&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">script</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /><br /></span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">div id</span><span style="COLOR: #000000">=</span><span style="COLOR: #800000">"</span><span style="COLOR: #800000">errors</span><span style="COLOR: #800000">"</span><span style="COLOR: #000000">&gt;&lt;/</span><span style="COLOR: #000000">div</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /><br /></span><span style="COLOR: #000000">&lt;%=</span><span style="COLOR: #000000"> form_local_tag :html </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> {:action </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> </span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">test_action</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">} </span><span style="COLOR: #000000">%&gt;</span><span style="COLOR: #000000"><br />  </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">input name</span><span style="COLOR: #000000">=</span><span style="COLOR: #800000">"</span><span style="COLOR: #800000">comment[title]</span><span style="COLOR: #800000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">/&gt;&lt;</span><span style="COLOR: #000000">br </span><span style="COLOR: #000000">/&gt;</span><span style="COLOR: #000000"><br />  </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">input name</span><span style="COLOR: #000000">=</span><span style="COLOR: #800000">"</span><span style="COLOR: #800000">comment[body]</span><span style="COLOR: #800000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">/&gt;&lt;</span><span style="COLOR: #000000">br </span><span style="COLOR: #000000">/&gt;</span><span style="COLOR: #000000"><br />  </span><span style="COLOR: #000000">&lt;%=</span><span style="COLOR: #000000"> submit_tag </span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">Create</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">%&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #000000">&lt;%=</span><span style="COLOR: #000000"> end_form_tag </span><span style="COLOR: #000000">%&gt;</span><span style="COLOR: #000000"><br /><br /></span><span style="COLOR: #000000">&lt;%=</span><span style="COLOR: #000000"> link_to_local </span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">Test</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">, :action </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> </span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">link_action()</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">%&gt;</span></div><br />上面演示了form_local_tag和link_to_local的使用，打开这个页面以后，可以关掉服务器测试，会发现它不请求服务器也能执行相应脚本。<br /><br />define_action定义一个脚本函数，call_script用来实现javascript和RJS代码的混合。当使用form_local_tag时，action方法的参数已经被处理过，所以可以直接在action中使用params.comment.title。<br /><br />当然现在还不完善，比如还只能使用转换完的页面模板，一些动态页面将看不出效果。要做到这点，需要用javascript实现一整套的ActionView辅助方法。<br /><br />下面提供一个针对rails 1.1.2的一个补丁文件：<br /><br /><a href="/Files/cpunion/script_action.zip">补丁文件下载</a><img src ="http://www.cppblog.com/cpunion/aggbug/7046.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2006-05-12 23:41 <a href="http://www.cppblog.com/cpunion/archive/2006/05/12/7046.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[RoR] ActionController::Caching模块缓存位置BUG</title><link>http://www.cppblog.com/cpunion/archive/2006/05/09/6814.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Tue, 09 May 2006 03:35:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2006/05/09/6814.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/6814.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2006/05/09/6814.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/6814.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/6814.html</trackback:ping><description><![CDATA[Caching模块用来实现caches_action/caches_page/fragment，普通用法没发现什么问题，问题在于使用下面的例子时，它不能缓存到正确的位置：<br /><br /><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"><span style="COLOR: #000000">class CacheController </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000"> ApplicationController<br />  caches_action </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">cache_one<br />  caches_page   </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">cache_two<br />  </span><span style="COLOR: #008000">#</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/images/dot.gif" /></span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">end</span></div><br /><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"><span style="COLOR: #000000">class TestController </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000"> ApplicationController<br />  def one<br />    render </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">inline </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">&lt;&lt;-</span><span style="COLOR: #000000">EOS<br />Test</span><span style="COLOR: #000000">::</span><span style="COLOR: #000000">one</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">br </span><span style="COLOR: #000000">/&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #000000">&lt;%=</span><span style="COLOR: #000000"> render_component </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">controller </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> </span><span style="FONT-WEIGHT: bold; COLOR: #000000">'</span><span style="FONT-WEIGHT: bold; COLOR: #000000">cache</span><span style="FONT-WEIGHT: bold; COLOR: #000000">'</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">action </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> </span><span style="FONT-WEIGHT: bold; COLOR: #000000">'</span><span style="FONT-WEIGHT: bold; COLOR: #000000">cache_one</span><span style="FONT-WEIGHT: bold; COLOR: #000000">'</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">%&gt;</span><span style="COLOR: #000000"><br />    EOS<br />  end<br /><br />  def two<br />    render </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">inline </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">&lt;&lt;-</span><span style="COLOR: #000000">EOS<br />Test</span><span style="COLOR: #000000">::</span><span style="COLOR: #000000">two</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">br </span><span style="COLOR: #000000">/&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #000000">&lt;%=</span><span style="COLOR: #000000"> render_component </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">controller </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> </span><span style="FONT-WEIGHT: bold; COLOR: #000000">'</span><span style="FONT-WEIGHT: bold; COLOR: #000000">cache</span><span style="FONT-WEIGHT: bold; COLOR: #000000">'</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">action </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> </span><span style="FONT-WEIGHT: bold; COLOR: #000000">'</span><span style="FONT-WEIGHT: bold; COLOR: #000000">cache_two</span><span style="FONT-WEIGHT: bold; COLOR: #000000">'</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">%&gt;</span><span style="COLOR: #000000"><br />    EOS<br />  end<br /><br />  </span><span style="COLOR: #008000">#</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/images/dot.gif" /></span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">end</span></div><br />cache_one和cache_two的实现就省略了。<br /><br />访问直接访问这2个action，能够在正确的目录下生成缓存文件。不过访问test/one和test/two就会出现缓存错误，2个缓存文件被生成到CACHE_ROOT/test下，试想如果在多个地方使用render_component，就会产生很多份一样内容的缓存。<br /><br />request会被传递给controller，当访问/test/one时，这个request保留有这个url。调用render_component时，会生成一个新的controller，这个request也被传递，不过url却还是/test/one，所以就有这个问题。<br /><br />修复：<br /><br /><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"><span style="COLOR: #000000">module ActionController </span><span style="COLOR: #008000">#</span><span style="COLOR: #008000">:nodoc:</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">  module Caching<br />    module Actions<br />      class ActionCacheFilter </span><span style="COLOR: #008000">#</span><span style="COLOR: #008000">:nodoc:</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        def before(controller)<br />          </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">unless</span><span style="COLOR: #000000"> </span><span style="COLOR: #800080">@actions</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">include</span><span style="COLOR: #000000">?</span><span style="COLOR: #000000">(controller</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">action_name</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">intern)<br />          url </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> controller</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">url_for(</span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">controller </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> controller</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">controller_name</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">action </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> controller</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">action_name)<br />          </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> cache </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> controller</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">read_fragment(url</span><span style="COLOR: #000000">.</span><span style="COLOR: #0000ff">split</span><span style="COLOR: #000000">(</span><span style="FONT-WEIGHT: bold; COLOR: #000000">"</span><span style="FONT-WEIGHT: bold; COLOR: #000000">://</span><span style="FONT-WEIGHT: bold; COLOR: #000000">"</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">.</span><span style="COLOR: #0000ff">last</span><span style="COLOR: #000000">)<br />            controller</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">rendered_action_cache </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> true<br />            controller</span><span style="COLOR: #000000">.</span><span style="COLOR: #0000ff">send</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">render_text</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000"> cache)<br />            false<br />          end<br />        end<br /><br />        def after(controller)<br />          </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">!</span><span style="COLOR: #800080">@actions</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">include</span><span style="COLOR: #000000">?</span><span style="COLOR: #000000">(controller</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">action_name</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">intern) </span><span style="COLOR: #000000">||</span><span style="COLOR: #000000"> controller</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">rendered_action_cache<br />          url </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> controller</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">url_for(</span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">controller </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> controller</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">controller_name</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">action </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> controller</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">action_name)<br />          controller</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">write_fragment(url</span><span style="COLOR: #000000">.</span><span style="COLOR: #0000ff">split</span><span style="COLOR: #000000">(</span><span style="FONT-WEIGHT: bold; COLOR: #000000">"</span><span style="FONT-WEIGHT: bold; COLOR: #000000">://</span><span style="FONT-WEIGHT: bold; COLOR: #000000">"</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">.</span><span style="COLOR: #0000ff">last</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000"> controller</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">response</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">body)<br />        end<br />      end<br />    end<br />  end<br />end<br /></span></div><br />通过替换controller和action来解决，测试结果正确。<br /><br />不过还有其它问题没修复，比如url中参数的问题，虽然调用render_component时我并没有传递参数，但它还是把参数给传递了。另外没有修复caches_page和fragment。<br /><br />其实这个问题是由render_component带来的，所以最好的修复办法当然是修复这个方法，让它处理正确的controller/action/params，暂时还没找出修复方法。<br /><br /><img src ="http://www.cppblog.com/cpunion/aggbug/6814.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2006-05-09 11:35 <a href="http://www.cppblog.com/cpunion/archive/2006/05/09/6814.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[RoR] 简单的角色权限检查插件</title><link>http://www.cppblog.com/cpunion/archive/2006/05/08/6790.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Mon, 08 May 2006 13:30:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2006/05/08/6790.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/6790.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2006/05/08/6790.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/6790.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/6790.html</trackback:ping><description><![CDATA[代码比较简单：<br /><br /><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"><span style="COLOR: #000000">module ActionController </span><span style="COLOR: #008000">#</span><span style="COLOR: #008000">:nodoc:</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000"><br />  class CheckGroupError </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000"> ActionControllerError </span><span style="COLOR: #008000">#</span><span style="COLOR: #008000">:nodoc:</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">    attr_reader </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">group_name<br />    def initialize(group_name)<br />      </span><span style="COLOR: #800080">@group_name</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> group_name<br />    end<br />  end<br />  <br />  class CheckRoleError </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000"> ActionControllerError </span><span style="COLOR: #008000">#</span><span style="COLOR: #008000">:nodoc:</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">    attr_reader </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">role_name<br />    def initialize(role_name)<br />      </span><span style="COLOR: #800080">@role_name</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> role_name<br />    end<br />  end<br />  <br />  class Base </span><span style="COLOR: #008000">#</span><span style="COLOR: #008000">:nodoc:</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">    def roles<br />      []<br />    end<br />    <br />    def groups<br />      []<br />    end<br />    <br />    def check_roles(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">role_args)<br />      role_args</span><span style="COLOR: #000000">.</span><span style="COLOR: #0000ff">each</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">do</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">role</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000"><br />        check_role(role)<br />      end<br />    end<br />    <br />    def check_groups(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">group_args)<br />      group_args</span><span style="COLOR: #000000">.</span><span style="COLOR: #0000ff">each</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">do</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">group</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000"><br />        check_group(group)<br />      end<br />    end<br />    <br />    def check_group(group)<br />      raise CheckGroupError</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">new(group</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">to_s) </span><span style="COLOR: #0000ff">unless</span><span style="COLOR: #000000"> groups()</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">include</span><span style="COLOR: #000000">?</span><span style="COLOR: #000000">(group</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">to_s)<br />    end<br />    <br />    def check_role(role)<br />      raise CheckRoleError</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">new(role</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">to_s)   </span><span style="COLOR: #0000ff">unless</span><span style="COLOR: #000000"> roles()</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">include</span><span style="COLOR: #000000">?</span><span style="COLOR: #000000">(role</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">to_s)      <br />    end<br />  end<br />  <br />end</span></div><br />只需要在ApplicationController中实现roles和groups这2个方法，对数据库模式没有任何限制，只要能保证这2个方法能够得到当前用户的角色和组即可。<br /><br />有4个check方法可用，可任意使用一个或多个。<br /><br />简单模拟测试一下：<br /><br /><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"><span style="COLOR: #000000">class ApplicationController </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000"> ActionController</span><span style="COLOR: #000000">::</span><span style="COLOR: #000000">Base<br />  def roles<br />    </span><span style="COLOR: #800080">%w</span><span style="COLOR: #000000">(add show)<br />  end<br /><br />  def groups<br />    </span><span style="COLOR: #800080">%w</span><span style="COLOR: #000000">(users)<br />  end<br />end</span></div><br /><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"><span style="COLOR: #000000">class TestController </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000"> ApplicationController<br />  def test1<br />    check_role </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">add<br />    render_text </span><span style="FONT-WEIGHT: bold; COLOR: #000000">"</span><span style="FONT-WEIGHT: bold; COLOR: #000000">OK</span><span style="FONT-WEIGHT: bold; COLOR: #000000">"</span><span style="COLOR: #000000"><br />  end<br /><br />  def test2<br />    check_role </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">add<br />    check_group </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">users<br />    render_text </span><span style="FONT-WEIGHT: bold; COLOR: #000000">"</span><span style="FONT-WEIGHT: bold; COLOR: #000000">OK</span><span style="FONT-WEIGHT: bold; COLOR: #000000">"</span><span style="COLOR: #000000"><br />  end<br /><br />  def test3<br />    check_groups </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">admin</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">users<br />    render_text </span><span style="FONT-WEIGHT: bold; COLOR: #000000">"</span><span style="FONT-WEIGHT: bold; COLOR: #000000">OK</span><span style="FONT-WEIGHT: bold; COLOR: #000000">"</span><span style="COLOR: #000000"><br />  end<br /><br />  def test4<br />    check_roles </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">add</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">remove<br />    render_text </span><span style="FONT-WEIGHT: bold; COLOR: #000000">"</span><span style="FONT-WEIGHT: bold; COLOR: #000000">OK</span><span style="FONT-WEIGHT: bold; COLOR: #000000">"</span><span style="COLOR: #000000"><br />  end<br />end</span></div><br />其中，test1、test2都会成功，而test3和test4则会失败显示异常，只需要处理rescue_action把它修改为自己的显示页面即可。<img src ="http://www.cppblog.com/cpunion/aggbug/6790.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2006-05-08 21:30 <a href="http://www.cppblog.com/cpunion/archive/2006/05/08/6790.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[RoR] Login Engine补丁</title><link>http://www.cppblog.com/cpunion/archive/2006/05/08/6778.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Mon, 08 May 2006 13:13:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2006/05/08/6778.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/6778.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2006/05/08/6778.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/6778.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/6778.html</trackback:ping><description><![CDATA[<p>Login Engine是非常好用的一个登录engine，不过也有个缺点，它把用户信息缓存在session里。如果用户每次修改完自己的资料，都把session更新的话，自然是不会有什么数据不同步的问题。不过试想这样一种情况：<br /><br />1、用户A登录；用户A的信息将保存在session[:user]里。<br />2、管理员操作用户A，修改用户A的资料并保存。<br />3、用户A刷新页面。</p>
		<p>如果显示用户资料是从session[:user]读取的话，显然用户A看到的是老的资料。<br /><br />正确的做法是管理员修改用户资料以后，把用户session里的内容也更新，当然这个实施起来有些困难，目前看来无法由用户ID获得对应的session。<br /><br />有朋友说session里不应该缓存用户信息，而应只保存用户ID。这是正确的，这样可以解决上面的问题，不过带来的问题是每次都要从数据库查询。<br /><br />如果每次刷新页面都从数据库重新读取用户信息，对性能影响是很大的。试想一下用户正在浏览一个论坛的帖子列表，这个页面可能所有用户看起来都是一样的，唯一不一样的地方是上面用户信息的显示。由于大部分内容都一样，可以使用缓存加快浏览速度。不过却由于session里只保存了用户ID，不得不读取数据库来获得用户信息，这样就把速度又拖慢了。<br /><br />所以应该把用户信息缓存起来，但要保证它能及时更新。方法自己做一个缓存管理器，能根据用户ID得到用户信息，也能随时更新它。<br /><br />学着ActionController::Caching做了一个UserManager，它可以根据线程配置来自动开关互斥器：<br />(/vender/plugins/login_engine/lib/login_engine/user_management.rb)<br /><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">
				<span style="COLOR: #000000">module UserManagement </span>
				<span style="COLOR: #008000">#</span>
				<span style="COLOR: #008000">:nodoc:</span>
				<span style="COLOR: #008000">
						<br />
				</span>
				<span style="COLOR: #000000">  class UnthreadedUserManager </span>
				<span style="COLOR: #008000">#</span>
				<span style="COLOR: #008000">:nodoc:</span>
				<span style="COLOR: #008000">
						<br />
				</span>
				<span style="COLOR: #000000">    def initialize </span>
				<span style="COLOR: #008000">#</span>
				<span style="COLOR: #008000">:nodoc:</span>
				<span style="COLOR: #008000">
						<br />
				</span>
				<span style="COLOR: #000000">      </span>
				<span style="COLOR: #800080">@users</span>
				<span style="COLOR: #000000"> </span>
				<span style="COLOR: #000000">=</span>
				<span style="COLOR: #000000"> {}<br />    end<br />    <br />    def get(user_id)<br />      </span>
				<span style="COLOR: #800080">@users</span>
				<span style="COLOR: #000000">[user_id]<br />    end<br />    <br />    def set(user_id</span>
				<span style="COLOR: #000000">,</span>
				<span style="COLOR: #000000"> user)<br />      </span>
				<span style="COLOR: #800080">@users</span>
				<span style="COLOR: #000000">[user_id] </span>
				<span style="COLOR: #000000">=</span>
				<span style="COLOR: #000000"> user<br />    end<br />  end<br />  <br />  module ThreadSafety </span>
				<span style="COLOR: #008000">#</span>
				<span style="COLOR: #008000">:nodoc:</span>
				<span style="COLOR: #008000">
						<br />
				</span>
				<span style="COLOR: #000000">    def get(user_id) </span>
				<span style="COLOR: #008000">#</span>
				<span style="COLOR: #008000">:nodoc:</span>
				<span style="COLOR: #008000">
						<br />
				</span>
				<span style="COLOR: #000000">      </span>
				<span style="COLOR: #800080">@mutex</span>
				<span style="COLOR: #000000">.</span>
				<span style="COLOR: #000000">synchronize { super }<br />    end<br />    def set(user_id</span>
				<span style="COLOR: #000000">,</span>
				<span style="COLOR: #000000"> user) </span>
				<span style="COLOR: #008000">#</span>
				<span style="COLOR: #008000">:nodoc:</span>
				<span style="COLOR: #008000">
						<br />
				</span>
				<span style="COLOR: #000000">      </span>
				<span style="COLOR: #800080">@mutex</span>
				<span style="COLOR: #000000">.</span>
				<span style="COLOR: #000000">synchronize { super }<br />    end<br />  end<br />  <br />  class UserManager </span>
				<span style="COLOR: #000000">&lt;</span>
				<span style="COLOR: #000000"> UnthreadedUserManager<br />    def initialize<br />      super<br />      </span>
				<span style="COLOR: #0000ff">if</span>
				<span style="COLOR: #000000"> ActionController</span>
				<span style="COLOR: #000000">::</span>
				<span style="COLOR: #000000">Base</span>
				<span style="COLOR: #000000">.</span>
				<span style="COLOR: #000000">allow_concurrency<br />        </span>
				<span style="COLOR: #800080">@mutex</span>
				<span style="COLOR: #000000"> </span>
				<span style="COLOR: #000000">=</span>
				<span style="COLOR: #000000"> Mutex</span>
				<span style="COLOR: #000000">.</span>
				<span style="COLOR: #000000">new<br />        UserManager</span>
				<span style="COLOR: #000000">.</span>
				<span style="COLOR: #0000ff">send</span>
				<span style="COLOR: #000000">(</span>
				<span style="COLOR: #000000">:</span>
				<span style="COLOR: #000000">include</span>
				<span style="COLOR: #000000">,</span>
				<span style="COLOR: #000000"> ThreadSafety)<br />      end<br />    end<br />  end<br />  <br />  @</span>
				<span style="COLOR: #800080">@user_manager</span>
				<span style="COLOR: #000000"> </span>
				<span style="COLOR: #000000">=</span>
				<span style="COLOR: #000000"> UserManagement</span>
				<span style="COLOR: #000000">::</span>
				<span style="COLOR: #000000">UserManager</span>
				<span style="COLOR: #000000">.</span>
				<span style="COLOR: #000000">new<br />  <br />  def set_current_user(user)<br />    </span>
				<span style="COLOR: #0000ff">return</span>
				<span style="COLOR: #000000"> session[</span>
				<span style="COLOR: #000000">:</span>
				<span style="COLOR: #000000">user_id] </span>
				<span style="COLOR: #000000">=</span>
				<span style="COLOR: #000000"> nil </span>
				<span style="COLOR: #0000ff">if</span>
				<span style="COLOR: #000000"> user</span>
				<span style="COLOR: #000000">.</span>
				<span style="COLOR: #000000">nil</span>
				<span style="COLOR: #000000">?</span>
				<span style="COLOR: #000000">
						<br />    session[</span>
				<span style="COLOR: #000000">:</span>
				<span style="COLOR: #000000">user_id] </span>
				<span style="COLOR: #000000">=</span>
				<span style="COLOR: #000000"> user</span>
				<span style="COLOR: #000000">.</span>
				<span style="COLOR: #000000">id<br />    cache_user(user)<br />  end<br />  <br />  def current_user<br />    get_user(session[</span>
				<span style="COLOR: #000000">:</span>
				<span style="COLOR: #000000">user_id])<br />  end<br />  <br />  def cache_user(user)<br />    </span>
				<span style="COLOR: #0000ff">return</span>
				<span style="COLOR: #000000"> </span>
				<span style="COLOR: #0000ff">if</span>
				<span style="COLOR: #000000"> user</span>
				<span style="COLOR: #000000">.</span>
				<span style="COLOR: #000000">nil</span>
				<span style="COLOR: #000000">?</span>
				<span style="COLOR: #000000">
						<br />    @</span>
				<span style="COLOR: #800080">@user_manager</span>
				<span style="COLOR: #000000">.</span>
				<span style="COLOR: #000000">set(user</span>
				<span style="COLOR: #000000">.</span>
				<span style="COLOR: #000000">id</span>
				<span style="COLOR: #000000">,</span>
				<span style="COLOR: #000000"> user)<br />  end<br />  <br />  def get_user(user_id)<br />    @</span>
				<span style="COLOR: #800080">@user_manager</span>
				<span style="COLOR: #000000">.</span>
				<span style="COLOR: #000000">get(user_id)<br />  end<br />end  </span>
		</div>
		<br />修改(/verdor/plugins/login_engine/lib/login_engine.rb)：<br /><br /><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"><span style="COLOR: #008000">#</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/images/dot.gif" /><img src="http://www.cppblog.com/images/dot.gif" />.</span><span><br /><strong><font color="#ff0000">require</font></strong></span><strong><font color="#ff0000"><span style="COLOR: #000000"> </span><span style="FONT-WEIGHT: bold; COLOR: #000000">'</span><span style="FONT-WEIGHT: bold; COLOR: #000000">login_engine/user_management</span></font></strong><span><strong><font color="#ff0000">'</font></strong><font color="#ff0000"><br /></font><br />module LoginEngine<br /> <strong> include UserManagement</strong><br />  </span><span style="COLOR: #008000">#</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/images/dot.gif" />.</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">end</span></div><br />加入上面加粗的2行。<br /><br />修改(/verdor/plugins/login_engine/lib/login_engine/authenticated_system.rb)，把session[:user]替换为session[:user_id]。<br /><br />修改(/verdor/plugins/login_engine/app/controllers/user_controller.rb):<br /><br /><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"><span style="COLOR: #000000">  def login<br />    </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> generate_blank<br />    </span><span style="COLOR: #800080">@user</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> User</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">new(params[</span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">user])<br />    </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> user </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> User</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">authenticate(params[</span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">user][</span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">login]</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000"> params[</span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">user][</span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">password])<br />      user</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">logged_in_at </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">Time</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">now<br />      user</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">save<br />      set_current_user(user)<br />      flash[</span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">notice] </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="FONT-WEIGHT: bold; COLOR: #000000">"</span><span style="FONT-WEIGHT: bold; COLOR: #000000">Login successful</span><span style="FONT-WEIGHT: bold; COLOR: #000000">"</span><span style="COLOR: #000000"><br />      redirect_to_stored_or_default </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">action </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> </span><span style="FONT-WEIGHT: bold; COLOR: #000000">'</span><span style="FONT-WEIGHT: bold; COLOR: #000000">home</span><span style="FONT-WEIGHT: bold; COLOR: #000000">'</span><span style="COLOR: #000000"><br />    </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"><br />      </span><span style="COLOR: #800080">@login</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> params[</span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">user][</span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">login]<br />      flash</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">now[</span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">warning] </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="FONT-WEIGHT: bold; COLOR: #000000">'</span><span style="FONT-WEIGHT: bold; COLOR: #000000">Login unsuccessful</span><span style="FONT-WEIGHT: bold; COLOR: #000000">'</span><span style="COLOR: #000000"><br />    end<br />  end</span></div><br /><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"><span style="COLOR: #000000">  def logout<br />    set_current_user(nil)<br />    redirect_to </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">action </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> </span><span style="FONT-WEIGHT: bold; COLOR: #000000">'</span><span style="FONT-WEIGHT: bold; COLOR: #000000">login</span><span style="FONT-WEIGHT: bold; COLOR: #000000">'</span><span style="COLOR: #000000"><br />  end</span></div><br /><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"><span style="COLOR: #000000">  def get_user_to_act_on<br />    </span><span style="COLOR: #800080">@user</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> current_user<br />  end</span></div><br />简单测试：<br /><br /><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"><span style="COLOR: #0000ff">require</span><span style="COLOR: #000000"> </span><span style="FONT-WEIGHT: bold; COLOR: #000000">'</span><span style="FONT-WEIGHT: bold; COLOR: #000000">login_engine</span><span style="FONT-WEIGHT: bold; COLOR: #000000">'</span><span style="COLOR: #000000"><br /><br />class ApplicationController </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000"> ActionController</span><span style="COLOR: #000000">::</span><span style="COLOR: #000000">Base<br />  include LoginEngine<br />  <br />  helper </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">user<br />  model </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">user<br />    <br />  before_filter </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">login_required<br />end</span></div><br /><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"><span style="COLOR: #000000">class ShowController </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000"> ApplicationController<br />  def show<br /></span><span style="COLOR: #000000">    render_text </span><span style="FONT-WEIGHT: bold; COLOR: #000000">"</span><span style="FONT-WEIGHT: bold; COLOR: #000000">User name: #{current_user.first_name}</span><span style="FONT-WEIGHT: bold; COLOR: #000000">"</span><span style="COLOR: #000000"><br />  end<br />end</span></div><br /><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"><span style="COLOR: #000000">class AdminController </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000"> ApplicationController<br />  def edit<br />    user </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> User</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">find(params[</span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">id])<br />    user</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">update_attributes(</span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">first_name </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> params[</span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">name])<br />    cache_user(user)<br />    render_text "User name: #{user.first_name}"<br />  end<br />end</span></div><br />一个简单的模拟：<br />1、用户A从IE登录，访问/show/show，将显示用户的名字。<br />2、管理员从FF登录，访问/show/show，将显示管理员名字。<br />3、管理员访问/show/show/2?name=hello，其中2是用户A的ID。这将把用户A的名字修改为hello。<br />4、用户A刷新页面，可以看到显示的用户名字已经发生变化。<br /><br />以上过程说这个修改已经达到目的。实现这个功能并不难，主要是为了保留Login Engine原有的功能不变。<br /><br />修改后的代码：<br /><a href="/Files/cpunion/login_engine.rar">www.cppblog.com/Files/cpunion/login_engine.rar</a><img src ="http://www.cppblog.com/cpunion/aggbug/6778.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2006-05-08 21:13 <a href="http://www.cppblog.com/cpunion/archive/2006/05/08/6778.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ruby on Rails 中文组</title><link>http://www.cppblog.com/cpunion/archive/2006/04/24/6140.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Mon, 24 Apr 2006 02:25:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2006/04/24/6140.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/6140.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2006/04/24/6140.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/6140.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/6140.html</trackback:ping><description><![CDATA[<table style="BORDER-RIGHT: #aa0033 1px solid; BORDER-TOP: #aa0033 1px solid; FONT-SIZE: small; BORDER-LEFT: #aa0033 1px solid; BORDER-BOTTOM: #aa0033 1px solid" align="center">
				<tbody>
						<tr>
								<td rowspan="3">
										<img height="58" alt="Google Groups" src="http://groups.google.com/groups/img/groups_medium.gif" width="150" />
								</td>
								<td align="middle" colspan="2">
										<b>Subscribe to Ruby on Rails 中文组</b>
								</td>
						</tr>
						<form action="http://groups.google.com/group/railscn/boxsubscribe">
								<tr>
										<td>Email: <input name="email" /></td>
										<td>
												<table style="BORDER-RIGHT: #ffcc33 2px outset; PADDING-RIGHT: 2px; BORDER-TOP: #ffcc33 2px outset; PADDING-LEFT: 2px; PADDING-BOTTOM: 2px; BORDER-LEFT: #ffcc33 2px outset; PADDING-TOP: 2px; BORDER-BOTTOM: #ffcc33 2px outset; BACKGROUND-COLOR: #ffcc33">
														<tbody>
																<tr>
																		<td>
																				<input type="submit" value="Subscribe" name="sub" />
																		</td>
																</tr>
														</tbody>
												</table>
										</td>
								</tr>
						</form>
						<tr>
								<td align="middle" colspan="2">
										<a href="http://groups.google.com/group/railscn">Browse Archives</a> at <a href="http://groups.google.com/">groups.google.com</a></td>
						</tr>
				</tbody>
		</table>
		<br />邮件列表交流方便些，欢迎大家订阅。<br /><br />注意：<br />1、不要使用邮件自动回复功能。<br />2、不要使用签名。<br />3、回复邮件注意裁剪引用。<br />4、使用文本邮件。<img src ="http://www.cppblog.com/cpunion/aggbug/6140.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2006-04-24 10:25 <a href="http://www.cppblog.com/cpunion/archive/2006/04/24/6140.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Groovy on Rails 0.1发布</title><link>http://www.cppblog.com/cpunion/archive/2006/04/07/5141.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Fri, 07 Apr 2006 08:59:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2006/04/07/5141.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/5141.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2006/04/07/5141.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/5141.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/5141.html</trackback:ping><description><![CDATA[简单测试了一下，语法比ruby稍罗嗦一点，不过也算是很简洁了。<br /><br />在WINDOWS下执行，遇到个小BUG，grails.bat第4行：if "%GRAILS_HOME"=="" goto grailsHomeNotSet是错误的，改成if "%GRAILS_HOME%"=="" goto grailsHomeNotSet就可以了。后面也有点小问题，干脆在LINUX下测试。<br /><br />照着Quick Start做了一下，还算顺利，不过例子怎么只给了个list呢？怎么也得把create/update/delete给完成嘛。<br /><br />猜着写了个create:<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">        @Property create </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> {<br />                [ post : </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> Post() ]<br />        }<br /><br />        @Property save </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> {<br />                </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> Post(</span><span style="color: rgb(0, 0, 255);">params</span><span style="color: rgb(0, 0, 0);">).save()<br />                redirect(action:list)<br />        }<br /></span></div><br />怎么存进去的不是我那个字符串，而是[Ljava.lang.String;@18b5a73呢。。<br /><br />又看了下文档，在controller里面是这么用的：<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">        @Property save </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> {<br />                def post </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> Post()<br />                post.properties </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">params</span><span style="color: rgb(0, 0, 0);"><br />                post.save()<br />                redirect(action:list)<br />        }<br /></span></div><br />其它都很相似：<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> PostController {<br /><br />        @Property index </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> { redirect(action:list) }<br /><br />        @Property list </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> {<br />                [ postList : Post.list() ]<br /><br />        }<br /><br />        @Property create </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> {<br />                [ post : </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> Post() ]<br />        }<br /><br />        @Property save </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> {<br />                def post </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> Post()<br />                post.properties </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">params</span><span style="color: rgb(0, 0, 0);"><br />                post.save()<br />                redirect(action:list)<br />        }<br /><br />        @Property show </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> {<br />                [ post : Post.</span><span style="color: rgb(0, 0, 255);">get</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 255);">params</span><span style="color: rgb(0, 0, 0);">[</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">id</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">]) ]<br />        }<br /><br />        @Property delete </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> {<br />                Post.</span><span style="color: rgb(0, 0, 255);">get</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 255);">params</span><span style="color: rgb(0, 0, 0);">[</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">id</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">]).delete()<br />                redirect(action:list)<br />        }<br /><br />        @Property edit </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> {<br />                [ post : Post.</span><span style="color: rgb(0, 0, 255);">get</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 255);">params</span><span style="color: rgb(0, 0, 0);">[</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">id</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">]) ]<br />        }<br /><br />        @Property update </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> {<br />                def post </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> Post.</span><span style="color: rgb(0, 0, 255);">get</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 255);">params</span><span style="color: rgb(0, 0, 0);">[</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">id</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">])<br />                post.properties </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">params</span><span style="color: rgb(0, 0, 0);"><br />                post.save()<br />                redirect(action:list)<br />        }<br />}<br /></span></div><br />语法上比RoR稍麻烦点。<br /><br />接着测试一下查询：<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">        @Property list </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> {<br />                def title </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">params</span><span style="color: rgb(0, 0, 0);">[</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">title</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">]<br />                def body </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">params</span><span style="color: rgb(0, 0, 0);">[</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">body</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">]<br />                def postList<br />                def c </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> Post.createCriteria()<br /><br />                </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">if (title != null &amp;&amp; title != "" &amp;&amp; body != null &amp;&amp; body != "")</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">                </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> (title </span><span style="color: rgb(0, 0, 0);">&amp;&amp;</span><span style="color: rgb(0, 0, 0);"> body)<br />                        postList </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> c{<br />                                like(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">title</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">%</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> title </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">%</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br />                                like(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">body</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">%</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> body </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">%</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br />                        }<br />                </span><span style="color: rgb(0, 0, 255);">else</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> (title)<br />                        postList </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> c{<br />                                like(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">title</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">%</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> title </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">%</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br />                        }<br />                </span><span style="color: rgb(0, 0, 255);">else</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> (body)<br />                        postList </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> c{<br />                                like(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">body</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">%</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> body </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">%</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br />                        }<br />                </span><span style="color: rgb(0, 0, 255);">else</span><span style="color: rgb(0, 0, 0);"><br />                        postList </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> Post.list()<br /><br />                [ postList : postList, post : </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> Post() ]<br />        }<br /></span></div><br />list.gsp里面添加：<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">           </span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">g:form action</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">list</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> method</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">post</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />               </span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">div </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">dialog</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />                </span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">table</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />                    </span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">tr </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">prop</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">&gt;<br />                        &lt;</span><span style="color: rgb(0, 0, 0);">td valign</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">top</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> style</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">text-align:left;</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> width</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">20%</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">&gt;<br />                            &lt;</span><span style="color: rgb(0, 0, 0);">label </span><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">title</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">Title:</span><span style="color: rgb(0, 0, 0);">&lt;/</span><span style="color: rgb(0, 0, 0);">label</span><span style="color: rgb(0, 0, 0);">&gt;<br />                        &lt;/</span><span style="color: rgb(0, 0, 0);">td</span><span style="color: rgb(0, 0, 0);">&gt;<br />                         &lt;</span><span style="color: rgb(0, 0, 0);">td valign</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">top</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> style</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">text-align:left;</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> width</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">80%</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 0, 255);">                            class</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">${hasErrors(bean:post,field:</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">title</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">errors</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">)}</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">&gt;<br />                            &lt;</span><span style="color: rgb(0, 0, 0);">input type</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">text</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> name</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">title</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> value</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">${post?.title}</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">/&gt;<br />                        &lt;/</span><span style="color: rgb(0, 0, 0);">td</span><span style="color: rgb(0, 0, 0);">&gt;<br />                    &lt;/</span><span style="color: rgb(0, 0, 0);">tr</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />                    </span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">tr </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">prop</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">&gt;<br />                        &lt;</span><span style="color: rgb(0, 0, 0);">td valign</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">top</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> style</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">text-align:left;</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> width</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">20%</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">&gt;<br />                            &lt;</span><span style="color: rgb(0, 0, 0);">label </span><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">body</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">Body:</span><span style="color: rgb(0, 0, 0);">&lt;/</span><span style="color: rgb(0, 0, 0);">label</span><span style="color: rgb(0, 0, 0);">&gt;<br />                        &lt;/</span><span style="color: rgb(0, 0, 0);">td</span><span style="color: rgb(0, 0, 0);">&gt;<br />                        &lt;</span><span style="color: rgb(0, 0, 0);">td valign</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">top</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> style</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">text-align:left;</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> width</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">80%</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"></span><span style="color: rgb(0, 0, 255);"><br />                            class</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">${hasErrors(bean:post,field:</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">body</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">errors</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">)}</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">&gt;<br />                            &lt;</span><span style="color: rgb(0, 0, 0);">input type</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">text</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> name</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">body</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> value</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">${post?.body}</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">/&gt;<br />                        &lt;/</span><span style="color: rgb(0, 0, 0);">td</span><span style="color: rgb(0, 0, 0);">&gt;<br />                    &lt;/</span><span style="color: rgb(0, 0, 0);">tr</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />               </span><span style="color: rgb(0, 0, 0);">&lt;/</span><span style="color: rgb(0, 0, 0);">table</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />               </span><span style="color: rgb(0, 0, 0);">&lt;/</span><span style="color: rgb(0, 0, 0);">div</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />               </span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">div </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">buttons</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />                     </span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">span </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">formButton</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />                        </span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">input type</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">submit</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> value</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Search</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">&gt;&lt;/</span><span style="color: rgb(0, 0, 0);">input</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />                     </span><span style="color: rgb(0, 0, 0);">&lt;/</span><span style="color: rgb(0, 0, 0);">span</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />               </span><span style="color: rgb(0, 0, 0);">&lt;/</span><span style="color: rgb(0, 0, 0);">div</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />           </span><span style="color: rgb(0, 0, 0);">&lt;/</span><span style="color: rgb(0, 0, 0);">g:form</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br /></span></div><br />groovy写代码挺烦的，局部变量也要def来定义？不定义就提示该变量不是对象的字段，跟很多脚本语言都不一样。如果从java上转过来，会觉得还是挺简洁的。<br /><br />借助spring、hibernate，Grails所做的就是整合，groovy这个语言好像并没有特别出众的地方，大部分东西在其它脚本语言里面都能看到。我觉得ruby更容易扩充，更自由。Grails要想成功，除非在效率上大幅度领先，就测试来看，并没有觉得很快，它也没提供个评测工具。据说ruby2.0也要重写虚拟机，如果ruby只是稍慢一些，自然还是选RoR比较好。<br /><img src ="http://www.cppblog.com/cpunion/aggbug/5141.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2006-04-07 16:59 <a href="http://www.cppblog.com/cpunion/archive/2006/04/07/5141.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>rails相关链接收集</title><link>http://www.cppblog.com/cpunion/archive/2006/03/23/4489.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Thu, 23 Mar 2006 04:53:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2006/03/23/4489.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/4489.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2006/03/23/4489.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/4489.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/4489.html</trackback:ping><description><![CDATA[http://wiki.rubyonrails.com/rails/pages/UnderstandingWhatMethodsGoWhere<br /><br />扩展ActiveRecord示例：<br />http://wiki.rubyonrails.com/rails/pages/ExtendingActiveRecordExample<br /><br />增加created_by和updated_by魔术字段：<br />http://wiki.rubyonrails.com/rails/pages/Howto+Add+created_by+and+updated_by<br /><br />嵌套集合（树）：<br />http://threebit.net/tutorials/nestedset/tutorial1.html<br />http://api.rubyonrails.com/classes/ActiveRecord/Acts/NestedSet/ClassMethods.html<br /><br />acts_as_threaded插件演示（可制作论坛、邮件线索）：<br />http://www.railtie.net/plugins/acts_as_threaded/threaded.swf<br /><img src ="http://www.cppblog.com/cpunion/aggbug/4489.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2006-03-23 12:53 <a href="http://www.cppblog.com/cpunion/archive/2006/03/23/4489.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>学习Ruby的一点体会</title><link>http://www.cppblog.com/cpunion/archive/2005/09/30/507.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Fri, 30 Sep 2005 04:12:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2005/09/30/507.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/507.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2005/09/30/507.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/507.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/507.html</trackback:ping><description><![CDATA[<P>仅仅是个人的一点体会。<BR><BR>首先它和python都属于动态解释型脚本语言，除此之外，有很多不同。<BR><BR>python是一个纯粹的脚本语言，以易学易用为主，Ruby更复杂一些，它的语法上更崇尚简洁，在语法和语义上比python要严格得多。虽然python要求以缩近来控制格式，但除了这点以外，其它方面Ruby都比它要严格，某些方面可以认为Ruby“更像是一门真正的语言”。<BR><BR><BR><BR>刚开始学，慢慢总结吧。<BR><BR>Ruby on Rails也照着做了一把，果然很酷，只是有些教程和目前的版本不一致。<BR><BR>对Ruby还不熟，要做项目也只好先学一下语言了，对Ruby感兴趣，一是看到了Ruby on Rails，另外就是真的去学习时，才发现它不是另一个python/js/vb/php等脚本语言。</P><img src ="http://www.cppblog.com/cpunion/aggbug/507.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2005-09-30 12:12 <a href="http://www.cppblog.com/cpunion/archive/2005/09/30/507.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ruby学习资源</title><link>http://www.cppblog.com/cpunion/archive/2005/09/28/477.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Wed, 28 Sep 2005 13:12:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2005/09/28/477.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/477.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2005/09/28/477.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/477.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/477.html</trackback:ping><description><![CDATA[<UL>
<LI>Ruby官方网站：<A href="http://www.ruby-lang.org">www.ruby-lang.org</A></LI>
<LI>Ruby国内中文站：<A href="http://www.ruby-cn.org/">http://www.ruby-cn.org/</A></LI>
<LI>Ruby on Rails：<A href="http://www.rubyonrails.org/">http://www.rubyonrails.org/</A></LI>
<LI>Ajax on Rails：<A href="http://www.onlamp.com/lpt/a/5944">http://www.onlamp.com/lpt/a/5944</A></LI></UL>
<P> </P><img src ="http://www.cppblog.com/cpunion/aggbug/477.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2005-09-28 21:12 <a href="http://www.cppblog.com/cpunion/archive/2005/09/28/477.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>