<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>bhuztez (bhuztez)</title>
    <link>https://ruby-china.org/bhuztez</link>
    <description></description>
    <language>en-us</language>
    <item>
      <title>[RubyConfChina2017 话题分享] 用 Erlang 快速开发 Web 快速开发框架</title>
      <description>&lt;p&gt;代码以及 slides 都在仓库里 &lt;a href="https://github.com/bhuztez/razor" rel="nofollow" target="_blank"&gt;https://github.com/bhuztez/razor&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="参考资料"&gt;参考资料&lt;/h2&gt;
&lt;p&gt;Regular Expression Matching in the Wild   &lt;a href="https://swtch.com/~rsc/regexp/regexp3.html" rel="nofollow" target="_blank"&gt;https://swtch.com/~rsc/regexp/regexp3.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Efficient submatch addressing for regular expressions  &lt;a href="https://laurikari.net/ville/regex-submatch.pdf" rel="nofollow" target="_blank"&gt;https://laurikari.net/ville/regex-submatch.pdf&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How Pony ORM translates Python generators to SQL queries  &lt;a href="https://av.tib.eu/media/19938" rel="nofollow" target="_blank"&gt;https://av.tib.eu/media/19938&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Programming Is Hard, Let's Go Shopping!  &lt;a href="https://blog.codinghorror.com/programming-is-hard-lets-go-shopping/" rel="nofollow" target="_blank"&gt;https://blog.codinghorror.com/programming-is-hard-lets-go-shopping/&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="补充"&gt;补充&lt;/h2&gt;
&lt;p&gt;因为时间有限删掉，或者一开始就没想到要加进去的一些东西，演讲结束后，在后面的交流中提到的，补充在这里&lt;/p&gt;
&lt;h3 id="C-c C-k大法好"&gt;C-c C-k 大法好&lt;/h3&gt;
&lt;p&gt;大部分框架都是用 inotify 之类的 API 来发现文件改动，有改动就自动重启 server。可是有时候你文件改了一半，连语法都有错误，此时重启就会出现一堆莫名其妙的错误。造框架的时候，要把这问题搞好也不容易。&lt;/p&gt;

&lt;p&gt;而用 Emacs 编辑 Erlang 代码，编辑好了，存一下，C-c C-k，会先编译成 beam 文件，假如编译失败，那就停了。假如生成了 beam 文件，就会通过热更新替换进去，不需要重启 server 就立即生效了，且能替换进去的至少是编译通过了的。而造框架并不需要去搞什么监听文件改动的事，省去了很多麻烦。&lt;/p&gt;

&lt;p&gt;所以，后面框架的设计，主要的一条就是在编译的时候，做更多检查，生成代码。而不是在运行期根据不同的配置有不同的行为。尽管做这些是为了开发的时候，热更新代码开发体验更好，同时因为代码都在编译期生成好了，运行期没有不必要的额外的开销。&lt;/p&gt;
&lt;h3 id="关于razor_url_dispatch"&gt;关于 razor_url_dispatch&lt;/h3&gt;
&lt;p&gt;有些网站 Apache 或者 nginx 为了一些特殊的活动页，配置了超级多的正则表达式规则，因为他们用的语言本身不支持 pattern matching，所以用正则表达式规则在弥补这个缺陷。但是这不是没有代价的。&lt;/p&gt;

&lt;p&gt;而在 razor_url_dispatch 里，你这么写直接会告诉你 rule conflict，不让你通过&lt;/p&gt;
&lt;pre class="highlight erlang"&gt;&lt;code&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="ni"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;special_page&lt;/span&gt;&lt;span class="p"&gt;}}).&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="ni"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"{id:integer}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;}}).&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;推荐的做法是像下面这样&lt;/p&gt;
&lt;pre class="highlight erlang"&gt;&lt;code&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="ni"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"{id:integer}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;}}).&lt;/span&gt;

&lt;span class="nf"&gt;handle_request&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;'GET'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;}})&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="n"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;handle_request&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;'GET'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;}})&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="n"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;而在 Erlang 里，下面这样的代码同样会提示你 Warning: this clause cannot match because ...&lt;/p&gt;
&lt;pre class="highlight erlang"&gt;&lt;code&gt;&lt;span class="nf"&gt;handle_request&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;'GET'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;}})&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="n"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;handle_request&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;'GET'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;}})&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="n"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;handle_request&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;'GET'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;}})&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="n"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;因为更合理的划分，我们在编译的时候就可以得到更多 warning。同时也简化了正则表达式的实现，可以使用 tagged DFA 来一遍扫描。&lt;/p&gt;

&lt;p&gt;失败人士的口号是，performance comes mostly from correctness。所以失败人士拒绝跑分。&lt;/p&gt;
&lt;h3 id="关于razor_db"&gt;关于 razor_db&lt;/h3&gt;
&lt;p&gt;为什么要支持子查询&lt;/p&gt;

&lt;p&gt;子查询和 aggregation 一起的时候，需要正确判断到底是 where 还是 having。我们不能只看表达式里有没有出现 aggregation。举个例子&lt;/p&gt;
&lt;pre class="highlight erlang"&gt;&lt;code&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subquery_having&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="nn"&gt;razor_db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nv"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;Name&lt;/span&gt;
        &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
           &lt;span class="nf"&gt;group_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
           &lt;span class="nv"&gt;Count&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
           &lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
             &lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
               &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                 &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                    &lt;span class="nv"&gt;C&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nv"&gt;Count&lt;/span&gt;
               &lt;span class="p"&gt;]))&lt;/span&gt;
      &lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;生成的代码是这样的&lt;/p&gt;
&lt;pre class="highlight erlang"&gt;&lt;code&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subquery_having&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Name&lt;/span&gt;
     &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nn"&gt;razor_db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                              &lt;span class="s"&gt;"SELECT T1.name FROM i1 AS T1 GROUP BY "&lt;/span&gt;
                              &lt;span class="s"&gt;"T1.name HAVING (EXISTS((SELECT T2.count "&lt;/span&gt;
                              &lt;span class="s"&gt;"AS count FROM i2 AS T2 WHERE (T2.count "&lt;/span&gt;
                              &lt;span class="s"&gt;"= count(T1.id)))))"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                              &lt;span class="p"&gt;[])];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;为什么一定要支持 Common Table Expression&lt;/p&gt;

&lt;p&gt;因为根据 SQL 标准，Common Table Expression 必须 fencing&lt;/p&gt;

&lt;p&gt;也就是我们把过滤条件写在最后的 SELECT 里，SQL 标准不允许 planner 把这个过滤条件挪到 Common Table Expression 里。所以必须把过滤条件写在 Common Table Expression 里。只要这个过滤条件里有参数，那么就意味着不可以手工写一段 SQL，拼在最前面了。&lt;/p&gt;
&lt;h3 id="在Erlang中表示HTML"&gt;在 Erlang 中表示 HTML&lt;/h3&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;br /&amp;gt;
{br, []}

&amp;lt;span&amp;gt;&amp;lt;a href="index.html"&amp;gt;Index&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;
{span, [], [{a, [{href, &amp;lt;&amp;lt;"index.html"&amp;gt;&amp;gt;}], [&amp;lt;&amp;lt;"Index"&amp;gt;&amp;gt;]}]}
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="更多Live Coding？"&gt;更多 Live Coding？&lt;/h3&gt;
&lt;p&gt;要注意的是，最后的 razor_api_example，就已经是接近完整的代码了。&lt;/p&gt;

&lt;p&gt;包括前面各种例子，都是用 pattern matching 来展示结果的，并没有太大必要增加 Live Coding。因为代码已经太多了。&lt;/p&gt;</description>
      <author>bhuztez</author>
      <pubDate>Tue, 19 Sep 2017 21:43:51 +0800</pubDate>
      <link>https://ruby-china.org/topics/34189</link>
      <guid>https://ruby-china.org/topics/34189</guid>
    </item>
    <item>
      <title>当前设置新手用户不能在 22:00-9:00 发贴</title>
      <description>&lt;p&gt;现在都 11 点了，还不能发，这么厉害？&lt;/p&gt;

&lt;p&gt;我无法回复&lt;/p&gt;

&lt;p&gt;注意提示的是到 9 点，现在都 11 点了&lt;/p&gt;</description>
      <author>bhuztez</author>
      <pubDate>Sun, 09 Jul 2017 10:54:40 +0800</pubDate>
      <link>https://ruby-china.org/topics/33438</link>
      <guid>https://ruby-china.org/topics/33438</guid>
    </item>
    <item>
      <title>其实你不需要 ORM</title>
      <description>&lt;p&gt;我是标题党，很多时候 ORM 还是很有必要的。&lt;/p&gt;

&lt;p&gt;不过有另外一些时候，明明知道要写的 SQL 是什么，不得不和 ORM 较劲，让 ORM 生成我期望的 SQL。不如让我直接写 SQL 吧。&lt;/p&gt;

&lt;p&gt;但是，ORM 做了一件事，能把查询出来的按行的结果，关联起来。没有 ORM，就只能手工做了。这也太麻烦了。&lt;/p&gt;

&lt;p&gt;我想了想，其实是很简单的。不到 300 行就能轻松实现这样的功能嘛。你也可以按这个思路自己实现。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/bhuztez/warm/blob/master/warm.py" rel="nofollow" target="_blank"&gt;https://github.com/bhuztez/warm/blob/master/warm.py&lt;/a&gt;&lt;/p&gt;</description>
      <author>bhuztez</author>
      <pubDate>Tue, 20 May 2014 11:21:48 +0800</pubDate>
      <link>https://ruby-china.org/topics/19407</link>
      <guid>https://ruby-china.org/topics/19407</guid>
    </item>
    <item>
      <title>n2o: nitrogen 威力加强版</title>
      <description>&lt;p&gt;&lt;a href="http://www.erlang-factory.com/static/upload/media/1394716419288323maximsokhatsky.pdf" rel="nofollow" target="_blank" title=""&gt;n2o&lt;/a&gt;在 nitrogen 框架的基础上，优化了速度，跑分不输 PHP&lt;/p&gt;

&lt;p&gt;利用 Erlang 强大的元编程能力，不仅能从 Erlang 代码快速生成 HTTP API，还能生成 JavaScript，前后端可以都只用 Erlang 了，再也不用考虑坑爹的 node.js 了。&lt;/p&gt;

&lt;p&gt;&lt;a href="/luikore" class="user-mention" title="@luikore"&gt;&lt;i&gt;@&lt;/i&gt;luikore&lt;/a&gt; 快出来跑分&lt;/p&gt;</description>
      <author>bhuztez</author>
      <pubDate>Sun, 16 Mar 2014 12:56:14 +0800</pubDate>
      <link>https://ruby-china.org/topics/17916</link>
      <guid>https://ruby-china.org/topics/17916</guid>
    </item>
    <item>
      <title>DeepThought: 屌丝版 Datalog 解释器</title>
      <description>&lt;p&gt;又来打小广告了&lt;/p&gt;

&lt;p&gt;DeepThought 只支持最最原始的 Datalog。现在已经有了 JavaScript 1.8.5，Python 2.7 以及 Ruby 1.9+ 三种语言的实现。&lt;/p&gt;

&lt;p&gt;&lt;a href="http://bhuztez.github.io/deepthought/" rel="nofollow" target="_blank" title=""&gt;这里&lt;/a&gt;有几个简单的例子， &lt;strong&gt;注意&lt;/strong&gt; 要用最新稳定版 FIREFOX 才能正常浏览。&lt;/p&gt;</description>
      <author>bhuztez</author>
      <pubDate>Fri, 14 Feb 2014 19:51:22 +0800</pubDate>
      <link>https://ruby-china.org/topics/17267</link>
      <guid>https://ruby-china.org/topics/17267</guid>
    </item>
    <item>
      <title>Gitto: 屌丝 git 托管工具</title>
      <description>&lt;p&gt;打个小广告&lt;/p&gt;

&lt;p&gt;这两天把以前的脚本重新整理了下，弄了个屌丝 git 托管工具，让你可以三步搭起你自己的 git 托管服务&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;不需要数据库&lt;/li&gt;
&lt;li&gt;不需要 Web 界面&lt;/li&gt;
&lt;li&gt;没有 branch 级别的 push 限制&lt;/li&gt;
&lt;li&gt;未经测试&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;太棒了，还不赶快试试 &lt;a href="https://github.com/bhuztez/gitto" rel="nofollow" target="_blank"&gt;https://github.com/bhuztez/gitto&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;P.S. 会尽快支持 Windows 的  &lt;img title=":smile:" alt="😄" src="https://twemoji.ruby-china.com/2/svg/1f604.svg" class="twemoji"&gt;&lt;/p&gt;</description>
      <author>bhuztez</author>
      <pubDate>Wed, 18 Dec 2013 20:32:07 +0800</pubDate>
      <link>https://ruby-china.org/topics/16295</link>
      <guid>https://ruby-china.org/topics/16295</guid>
    </item>
    <item>
      <title>不小心点到了 feed</title>
      <description>&lt;p&gt;发现点后退怎么也回不去了。&lt;/p&gt;</description>
      <author>bhuztez</author>
      <pubDate>Tue, 10 Dec 2013 12:28:48 +0800</pubDate>
      <link>https://ruby-china.org/topics/16114</link>
      <guid>https://ruby-china.org/topics/16114</guid>
    </item>
    <item>
      <title>boy 还是 girl?</title>
      <description>&lt;p&gt;无意间看到 &lt;a href="http://www.infoq.com/cn/news/2013/12/the-power-of-a-pronoun" rel="nofollow" target="_blank" title=""&gt;Node.js 社区：一个人称代词引发的论战&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;让我想起了一个很头疼的问题&lt;/p&gt;

&lt;p&gt;比如&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;He who is not an Erlang fanboy, does not understand OO.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;为了不必要的麻烦，应该改成下面哪个才对？&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;u&gt;They&lt;/u&gt; who is not an Erlang &lt;u&gt;fanboy&lt;/u&gt;, does not understand OO.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;They&lt;/u&gt; who is not an Erlang &lt;u&gt;fangirl&lt;/u&gt;, does not understand OO.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;She&lt;/u&gt; who is not an Erlang &lt;u&gt;fanboy&lt;/u&gt;, does not understand OO.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;She&lt;/u&gt; who is not an Erlang &lt;u&gt;fangirl&lt;/u&gt;, does not understand OO.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="/hooopo" class="user-mention" title="@hooopo"&gt;&lt;i&gt;@&lt;/i&gt;hooopo&lt;/a&gt; &lt;a href="/fredwu" class="user-mention" title="@fredwu"&gt;&lt;i&gt;@&lt;/i&gt;fredwu&lt;/a&gt; &lt;a href="/knwang" class="user-mention" title="@knwang"&gt;&lt;i&gt;@&lt;/i&gt;knwang&lt;/a&gt; &lt;a href="/blacktulip" class="user-mention" title="@blacktulip"&gt;&lt;i&gt;@&lt;/i&gt;blacktulip&lt;/a&gt; &lt;a href="/ywencn" class="user-mention" title="@ywencn"&gt;&lt;i&gt;@&lt;/i&gt;ywencn&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;另外，这不代表我支持这种假惺惺的避重就轻的行为。另外的另外，送一个鸡汤链接，&lt;a href="http://prog21.dadgum.com/184.html" rel="nofollow" target="_blank" title=""&gt;Three Years in an Alternate Universe&lt;/a&gt;&lt;/p&gt;</description>
      <author>bhuztez</author>
      <pubDate>Wed, 04 Dec 2013 20:44:35 +0800</pubDate>
      <link>https://ruby-china.org/topics/16012</link>
      <guid>https://ruby-china.org/topics/16012</guid>
    </item>
    <item>
      <title>Ruby 中文群组</title>
      <description>&lt;p&gt;&lt;a href="https://groups.google.com/forum/#!forum/rubygroups" rel="nofollow" target="_blank"&gt;https://groups.google.com/forum/#!forum/rubygroups&lt;/a&gt;&lt;/p&gt;</description>
      <author>bhuztez</author>
      <pubDate>Sat, 09 Nov 2013 16:45:26 +0800</pubDate>
      <link>https://ruby-china.org/topics/15416</link>
      <guid>https://ruby-china.org/topics/15416</guid>
    </item>
    <item>
      <title>SQL is Agile</title>
      <description>&lt;p&gt;&lt;a href="http://lucumr.pocoo.org/2012/12/29/sql-is-agile/" rel="nofollow" target="_blank"&gt;http://lucumr.pocoo.org/2012/12/29/sql-is-agile/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;我也是这么认为的。最开始的时候，总是要先搞清楚数据本身的约定以及数据之间的联系，第一步总是要 normalize 的，schemaless 在这里并不能带来什么帮助，反而更麻烦了。从这个角度来看，MongoDB 显然不适合用来开发原型。&lt;/p&gt;

&lt;p&gt;假如你不熟悉 SQL，可以看看这个博客&lt;/p&gt;

&lt;p&gt;&lt;a href="http://database-programmer.blogspot.com/" rel="nofollow" target="_blank"&gt;http://database-programmer.blogspot.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;接着才是 RDBMS 处理不好的地方要 denormalize，有必要的话再引入别的类型的数据库&lt;/p&gt;

&lt;p&gt;你可以放弃几乎所有 JOIN，获得接近线性扩展的集群能力。这是 MySQL NDB，Mnesia 之类的数据库了。&lt;/p&gt;

&lt;p&gt;也可以预先定义好需要哪些 JOIN，把相关数据放在一起，从而为这些 JOIN 优化。Google F1 和 Oracle 的 Table Cluster 就是这么干的。有没有开源实现，我还没了解过，你可以来补充一下。&lt;/p&gt;

&lt;p&gt;&lt;a href="http://research.google.com/pubs/pub38125.html" rel="nofollow" target="_blank"&gt;http://research.google.com/pubs/pub38125.html&lt;/a&gt;
&lt;a href="http://docs.oracle.com/cd/E11882_01/server.112/e25789/tablecls.htm#i25478" rel="nofollow" target="_blank"&gt;http://docs.oracle.com/cd/E11882_01/server.112/e25789/tablecls.htm#i25478&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;再后面就得等着被 CAP 坑了。&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blog.nahurst.com/visual-guide-to-nosql-systems" rel="nofollow" target="_blank"&gt;http://blog.nahurst.com/visual-guide-to-nosql-systems&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CouchDB 用来做 aggregation，通过放弃 consistency，换取用空间换时间的机会
Memcachedb 之类的用来做缓存
BigTable 之类的，没用过，据说很有用&lt;/p&gt;</description>
      <author>bhuztez</author>
      <pubDate>Thu, 10 Jan 2013 11:25:09 +0800</pubDate>
      <link>https://ruby-china.org/topics/7927</link>
      <guid>https://ruby-china.org/topics/7927</guid>
    </item>
  </channel>
</rss>
