<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>kevinhua (Kevin Hua)</title>
    <link>https://ruby-china.org/kevinhua</link>
    <description>潜伏在医药行业，游走在IT边缘</description>
    <language>en-us</language>
    <item>
      <title>ActionCable 学习笔记</title>
      <description>&lt;p&gt;&lt;strong&gt;[简单的笔记，待进一步编辑]&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;看着 Ruby-China 也用上了 ActionCable，然后看了一下 China RailsCasts 转载的 DHH 的教学视频，感觉讲得非常好。&lt;/p&gt;

&lt;p&gt;其实看了一下，ActionCable 上手也非常简单，而且 Rails 还内置了 Generator，一句简单的命令就可以搞定 Scaffold 文件：&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails generate channel NAME &lt;span class="o"&gt;[&lt;/span&gt;method method] &lt;span class="o"&gt;[&lt;/span&gt;options]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;避开技术流程简单来说，最常见的应用场景就是：&lt;/p&gt;

&lt;p&gt;前端递交表单-&amp;gt;Commit 并保存-&amp;gt;通过 after-create-commit 触发任务并排队执行-&amp;gt;服务器端将数据 (可以是渲染后的数据)broadcast-&amp;gt;客户端接收到数据并执行&lt;/p&gt;

&lt;p&gt;简单来分解一下：&lt;/p&gt;

&lt;p&gt;1) Form (例如 Ruby China 的“发布新话题”表单)&lt;/p&gt;

&lt;p&gt;2) Commit (例如 Ruby China 的 TopicsController#Create)&lt;/p&gt;

&lt;p&gt;3) 在模型中设定 after-create-commit (例如 Ruby China 的 Topic Model)&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;after_create_commit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="no"&gt;TopicBroadcastJob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perform_later&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;创建 Job 也很简单，一句简单的命令就可以搞定：&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails generate job NAME &lt;span class="o"&gt;[&lt;/span&gt;options]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails generate TopicBroadcastJob
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;5) 通过 TopicBroadcastJob，将服务器端数据 broadcast [这里就参考 DHH 视频中的例子]&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TopicBroadcastJob&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationJob&lt;/span&gt;
  &lt;span class="n"&gt;queue_as&lt;/span&gt; &lt;span class="ss"&gt;:default&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;perform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;ActionCable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;broadcast&lt;/span&gt; &lt;span class="s1"&gt;'stream_channel'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;message: &lt;/span&gt;&lt;span class="n"&gt;render_topic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="kp"&gt;private&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;render_topic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="no"&gt;ApplicationController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;partial: &lt;/span&gt;&lt;span class="s1"&gt;'topics/topic'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;locals: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;topic: &lt;/span&gt;&lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;6) 客户端接收到数据并执行，例如将接收到的数据 (可以是用新建记录渲染过的 partial)&lt;/p&gt;
&lt;pre class="highlight coffeescript"&gt;&lt;code&gt;&lt;span class="na"&gt;received&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'#topics'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="na"&gt;append&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'topic'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;当然，在使用 ActionCable 之前，还需要简单地设置：&lt;/p&gt;

&lt;p&gt;1) 在 Routes 中添加一句：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;mount&lt;/span&gt; &lt;span class="no"&gt;ActionCable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'/cable'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;2) 在 config 目录中，增加一个 cable.yml，大致内容如下：&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;development&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;adapter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;async&lt;/span&gt;

&lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;adapter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;async&lt;/span&gt;

&lt;span class="na"&gt;production&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;adapter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;redis&lt;/span&gt;
  &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;redis://localhost:6379/1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;3) 在 Layouts 头部增加一句：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sx"&gt;%= action_cable_meta_tag %&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;4) 通过 Generator 生成前后端文件：&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails g channel stream
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;将在 app/assets/javascripts 中生成前端 (客户端)Coffee 文件，在 app/channels 生成后端 (服务器端文件)。&lt;/p&gt;</description>
      <author>kevinhua</author>
      <pubDate>Sat, 12 Nov 2016 22:09:55 +0800</pubDate>
      <link>https://ruby-china.org/topics/31583</link>
      <guid>https://ruby-china.org/topics/31583</guid>
    </item>
    <item>
      <title>两个故事：Emo 和海星</title>
      <description>&lt;p&gt;&lt;img src="//l.ruby-china.com/photo/2014/428ad24f8cc04f44ae74b3fcc263d69a.jpg" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Emo 的故事&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;在一个岛上，有一位长年驻守的动物学家，他专门从事对猴子的研究工作。一天，一只小猴子出生了。动物学家给它取名叫"依侔 (Emo)"。在一个清晨，出生后不久的依侔独自向海边走去，那一刻，岛上的猴子们全都安静了，整个小岛也宁静了，动物学家那一刻也停住了，大家好象都在等待着什么，所有猴子的眼睛和动物学家的眼睛都随着依侔在向海边移动。&lt;/p&gt;

&lt;p&gt;为什么会这样？原来，在依侔出生前，岛上的猴子们生生世世没有一个曾到过海边，没有一个猴子碰过海水。至于什么原因，动物学家也百思不得其解，自他见到岛上第一只猴子起，他就从未见过有哪只猴子靠近过海水。他也曾试着用各种方法让猴子们去接近大海，但都未成功，或许是第一只猴子就不曾到过海边的原因，以后在这个岛上出生的猴子就没有一只敢靠近海的。&lt;/p&gt;

&lt;p&gt;不一会，依侔走到了海边，它先用一只脚沾了沾清凉的海水，然后又用另一只脚也沾了沾，随后大家发现依侔竟跳进海水，用两只胳膊拍打起海水来，样子看上去很欢快的样子，它在海水中跑着、跳着，并且还招呼其他的猴子跟他一起来玩海水，可是，其他的猴子没有一个敢过来的，依侔仍旧在海边玩着。&lt;/p&gt;

&lt;p&gt;这一天，就这样过去了，但这一天，对那位动物学家来说可是非同寻常的一天，第一次，一只猴子，自己下水了。&lt;/p&gt;

&lt;p&gt;以后，一直都是依侔独自在海边玩耍，在海里洗澡。&lt;/p&gt;

&lt;p&gt;不久，岛上又出生了一只小猴子。在一个温暖的早晨，整个小岛又一次宁静了，原来所有猴子和那位动物学家看到依侔竟然拉着那只小猴子的手，向海边走去。一会的工夫，他们到了海边，随后大家见到它们俩在海水中玩得是那样开心、欢畅，它们向岛上的其他猴子招手，让它们也到海水中一起玩耍，但，最终仍只是它们俩在快乐地玩着。动物学家在海边观察着它们，竟兴奋的一整夜没睡觉。&lt;/p&gt;

&lt;p&gt;不久，岛上又出生了一只小猴子，同样是依侔带着它到海边，接触海水，最后它们在海中高兴地跳着。就这样，每出生一只猴子，依侔都会带它去海边玩耍。&lt;/p&gt;

&lt;p&gt;现在依侔已有了 98 个小玩伴，直到有一天，岛上又出生了一只猴子，它是依侔在这个岛上出生后的第一百只猴子，但动物学家和其他岛上的猴子们却发觉这次依侔并没有来牵它的手去海边。&lt;/p&gt;

&lt;p&gt;后来，动物学家和岛上所有的猴子看到，那只小猴子竟然象当初依侔那样独自走向海边，小岛又一次宁静了，当大家的目光跟着小猴子移到海边时，整个小岛欢呼了！&lt;/p&gt;

&lt;p&gt;原来依侔早已在海边等它了。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;海星的故事&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;在大海边，每当退潮的时候，海边总会有一些搁浅的海星，这些海星如果离开了大海就活不了多久了。&lt;/p&gt;

&lt;p&gt;一天黄昏，在澳洲的海滩上，有一位老先生拄着拐杖散步，遇到了一个小女孩。他看到这个小女孩不断地捡起沙滩上的东西往海里扔，不禁好奇地问道：“小姑娘，你在打水漂吗？”&lt;/p&gt;

&lt;p&gt;小女孩说：“不是啊，老爷爷，我看到沙滩上有好多海星，明天一早太阳出来，它们都会被晒死，我觉得那样太可怜了，所以我要把海星们投回大海。”&lt;/p&gt;

&lt;p&gt;这位老人早已看尽人生百态，不禁莞尔。他说：“小姑娘你别傻了，这条海岸有多长、海星有多少，凭你一个人，怎么可能救活所有的海星呢？”&lt;/p&gt;

&lt;p&gt;小女孩又默默地捡起一只海星，丢向海中，然后说：“老爷爷，我知道凭我一个人的力量，救不了全部的海星，但是，我能救多少就救多少啊。”&lt;/p&gt;

&lt;p&gt;老人又说道：“小姑娘，你别徒劳了，谁会在乎这些啊？”&lt;/p&gt;

&lt;p&gt;小女孩微笑，仍是弯下腰再拾起另一只海星：“这只海星在乎，这只也在乎啊！我知道当我捡起这一只海星并把‘它’丢进海里的时候，我已经改变了‘它’的命运。”&lt;/p&gt;

&lt;p&gt;小女孩仍是弯下腰再拾起了另一只海星。丢进海中说：“我又改变了一只海星的命运了。”&lt;/p&gt;</description>
      <author>kevinhua</author>
      <pubDate>Sat, 22 Mar 2014 14:55:21 +0800</pubDate>
      <link>https://ruby-china.org/topics/18095</link>
      <guid>https://ruby-china.org/topics/18095</guid>
    </item>
    <item>
      <title>Discourse 的代码真够冗余的</title>
      <description>&lt;p&gt;毫无疑问，Discourse 的交互功能超赞。但代码量真多。&lt;/p&gt;

&lt;p&gt;就简单的模型层面来说，Models 代码一堆，Libs 里代码又是一堆，重复来，重复去。&lt;/p&gt;</description>
      <author>kevinhua</author>
      <pubDate>Fri, 07 Mar 2014 00:40:10 +0800</pubDate>
      <link>https://ruby-china.org/topics/17708</link>
      <guid>https://ruby-china.org/topics/17708</guid>
    </item>
    <item>
      <title>Peat.io 准备用 Discourse 重构?</title>
      <description>&lt;p&gt;Peat.io 准备基于 Discourse 重构？&lt;/p&gt;</description>
      <author>kevinhua</author>
      <pubDate>Mon, 10 Feb 2014 15:27:08 +0800</pubDate>
      <link>https://ruby-china.org/topics/17145</link>
      <guid>https://ruby-china.org/topics/17145</guid>
    </item>
    <item>
      <title>学习兴趣调查</title>
      <description>&lt;p&gt;亲爱的朋友，您好！&lt;/p&gt;

&lt;p&gt;我们正在策划建立一个在线培训网站，在筹备阶段，我们很希望集思广益，了解您对在线培训的需求和建议。&lt;/p&gt;

&lt;p&gt;我们准备了一个非常短暂仅包含 9 个问题的问卷，您可能需要 5 分钟完成这份问卷，感谢您的宝贵时间。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.surveymonkey.com/s/QR2YWXP" rel="nofollow" target="_blank"&gt;https://www.surveymonkey.com/s/QR2YWXP&lt;/a&gt;&lt;/p&gt;</description>
      <author>kevinhua</author>
      <pubDate>Fri, 27 Dec 2013 16:37:10 +0800</pubDate>
      <link>https://ruby-china.org/topics/16464</link>
      <guid>https://ruby-china.org/topics/16464</guid>
    </item>
    <item>
      <title>Simple Word document templating using Ruby and XML</title>
      <description>&lt;p&gt;Cited from: &lt;a href="http://tomasvarsavsky.com/2009/04/04/simple-word-document-templating-using-ruby-and-xml/" rel="nofollow" target="_blank"&gt;http://tomasvarsavsky.com/2009/04/04/simple-word-document-templating-using-ruby-and-xml/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In my current project we have a requirement to merge simple data into Microsoft Word document templates. Ruby comes with the WIN32OLE library which can manipulate Office documents. WIN32OLE has a few major downsides — it only runs on Windows, it requires Microsoft Office to be installed and it works by sending commands to Word itself to perform operations. Using Word as a back end system for a web application used by 50 people made us nervous so a different approach was needed. We came up with a combination of Ruby, Office Open XML file format, XML processing with Nokogiri and native Zip libraries that works.
Office Open XML file formats
The new Office file formats (.docx, .xlsx, .pptx files) are basically a zipped collection of XML files. We focused on Word files (.docx) but this approach would work with any of the other types of files as well. The specification for the format weighs in at several thousand pages. Producing a file from scratch without a purpose built library that handles all the intricacies of the format would be quite a task. Instead, we drafted the templates in Word and placed markers to tell our templating engine where to insert values. We created document properties which reference data values and added these as fields into the document in the place where the values should be inserted. For example, we could have fields like:&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;label_tag&lt;/span&gt; &lt;span class="c1"&gt;#{data[:user].name}&lt;/span&gt;
&lt;span class="n"&gt;label_tag&lt;/span&gt; &lt;span class="c1"&gt;#{data[:user].address}&lt;/span&gt;
&lt;span class="n"&gt;label_tag&lt;/span&gt; &lt;span class="c1"&gt;#{data[:booking].number}&lt;/span&gt;
&lt;span class="n"&gt;label_tag&lt;/span&gt; &lt;span class="c1"&gt;#{data[:booking].items.collect{|i| i.name}.join(‘,’)}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If it looks a bit like Ruby code, it’s because it is! The expressions get evaluated by our templating engine and the results are inserted into the document. Ruby in Word documents, a world first?
Opening the documents
To read and create documents we need to unzip and re-zip the document. We had trouble using Ruby’s standard RubyZip library. For some reason Word gave a nasty warning when opening files created with RubyZip. Our application has to run on Windows, Linux and Mac so we created an adapter that delegated to standard operating system zip executables based on the host platform. To keep it fast, we extract and re-added only the files that we need to work on. This is important because some documents can become very large when they contain embedded objects such as images.
Processing the template
The document content can be found in the file word/document.xml inside the zip archive. The fields in the template come out as fldSimple tags that look like this:&lt;/p&gt;

&lt;p&gt;Template Field: User Name&lt;/p&gt;

&lt;p&gt;To process the document.xml we simply need to find all the fields that have the text label_tag in the w:instr attribute:
xml.xpath(“//w:fldSimple[contains(&lt;a href="/w" class="user-mention" title="@w"&gt;&lt;i&gt;@&lt;/i&gt;w&lt;/a&gt;:instr, 'label_tag')]“).each do |element|&lt;/p&gt;
&lt;h2 id="process each element here"&gt;process each element here&lt;/h2&gt;
&lt;p&gt;end
The rest is simple. We extract the expression in the element text using a regular expression, evaluate it and insert it back into the XML which ends up looking like this:&lt;/p&gt;

&lt;p&gt;Tomas Varsasvky&lt;/p&gt;

&lt;p&gt;We add the attribute fldLock with value true to make the field read-only so the user cannot change it when they open the document.
We also have tags to create lists, insert rows into tables and duplicate sections in the document. These are a bit more complicated in their XML manipulation. Beware, we had a few issues dealing with Word’s nasty XML which can vary a bit between versions and sometimes do unexpected things with formatting.
Conclusion
This approach worked really well for us and I would recommend it for simple field merging.&lt;/p&gt;</description>
      <author>kevinhua</author>
      <pubDate>Wed, 18 Sep 2013 11:42:05 +0800</pubDate>
      <link>https://ruby-china.org/topics/14205</link>
      <guid>https://ruby-china.org/topics/14205</guid>
    </item>
    <item>
      <title>重写 Json Presenter，是用 rabl, jbuilder 这一类好，还是 AMS 这一类好</title>
      <description>&lt;p&gt;Active Model Serializer 更符合 DRY 原则一些；&lt;/p&gt;

&lt;p&gt;Rabl, jBuilder 更容易理解和编写，直接和 views 写在同一文件夹下。&lt;/p&gt;</description>
      <author>kevinhua</author>
      <pubDate>Thu, 25 Apr 2013 22:46:17 +0800</pubDate>
      <link>https://ruby-china.org/topics/10512</link>
      <guid>https://ruby-china.org/topics/10512</guid>
    </item>
    <item>
      <title>TeaLeaf 的课有优惠吗?</title>
      <description>&lt;p&gt;&lt;a href="/knwang" class="user-mention" title="@knwang"&gt;&lt;i&gt;@&lt;/i&gt;knwang&lt;/a&gt; TeaLeaf 的课有优惠吗？&lt;/p&gt;

&lt;p&gt;我有个侄女准备介绍她学习 Rails。&lt;/p&gt;</description>
      <author>kevinhua</author>
      <pubDate>Sun, 21 Apr 2013 11:40:51 +0800</pubDate>
      <link>https://ruby-china.org/topics/10373</link>
      <guid>https://ruby-china.org/topics/10373</guid>
    </item>
    <item>
      <title>Handlebars 截断字符的 helpers</title>
      <description>&lt;p&gt;Handlebars 截断字符的 helpers，使用时如下：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{{trimString name 10}}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;就可以将 name 截成长度为 10 的字符，支持中英文字符。&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Handlebars.registerHelper('trimString', function(passedString,len) {
  if(!passedString) { return ''; }
  if(!len) {return new Handlebars.SafeString(passedString); }
  var theString = passedString + "";
  var a = 0;
  var i = 0;
  var temp = '';
  for (i=0;i&amp;lt;theString.length;i++) {
    if (theString.charCodeAt(i)&amp;gt;255) {
      a+=2;
    }
    else {
      a++;
    }
    if(a &amp;gt; len) { return new Handlebars.SafeString(temp+"..."); }
    temp += theString.charAt(i);     
  }
  return new Handlebars.SafeString(theString); 
});
&lt;/code&gt;&lt;/pre&gt;</description>
      <author>kevinhua</author>
      <pubDate>Sat, 20 Apr 2013 13:57:47 +0800</pubDate>
      <link>https://ruby-china.org/topics/10361</link>
      <guid>https://ruby-china.org/topics/10361</guid>
    </item>
    <item>
      <title>网注册了一个域名，siqi.tv</title>
      <description>&lt;p&gt;网注册了一个域名，siqi.tv&lt;/p&gt;

&lt;p&gt;留着以后用。&lt;/p&gt;</description>
      <author>kevinhua</author>
      <pubDate>Fri, 19 Apr 2013 23:29:54 +0800</pubDate>
      <link>https://ruby-china.org/topics/10354</link>
      <guid>https://ruby-china.org/topics/10354</guid>
    </item>
    <item>
      <title>闲得无聊，将三四年前停掉的一个网站上线了</title>
      <description>&lt;p&gt;闲得无聊，将三四年前停掉的一个网站上线了&lt;/p&gt;

&lt;p&gt;VP 时尚网： &lt;a href="http://www.voguepod.com" rel="nofollow" target="_blank" title=""&gt;www.voguepod.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;准备稍微改版一下，当年的美工实在差呀。&lt;/p&gt;</description>
      <author>kevinhua</author>
      <pubDate>Fri, 22 Mar 2013 01:58:26 +0800</pubDate>
      <link>https://ruby-china.org/topics/9666</link>
      <guid>https://ruby-china.org/topics/9666</guid>
    </item>
    <item>
      <title>三文鱼协议 (Salmon Protocol)</title>
      <description>&lt;p&gt;三文鱼协议 (Salmon Protocol)&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.salmon-protocol.org/salmon-protocol-summary" rel="nofollow" target="_blank"&gt;http://www.salmon-protocol.org/salmon-protocol-summary&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;建议是不是要增加一个新节点：协议或标准 (Protocols or Standards)&lt;/p&gt;</description>
      <author>kevinhua</author>
      <pubDate>Sun, 10 Mar 2013 11:40:56 +0800</pubDate>
      <link>https://ruby-china.org/topics/9293</link>
      <guid>https://ruby-china.org/topics/9293</guid>
    </item>
    <item>
      <title>有哪些在线教育网站? 找人开发类似网站的成本为多少?</title>
      <description>&lt;p&gt;Udemy: &lt;a href="http://www.36kr.com/p/160565.html" rel="nofollow" target="_blank"&gt;http://www.36kr.com/p/160565.html&lt;/a&gt;
Lynda: &lt;a href="http://www.36kr.com/p/200787.html?vt=0" rel="nofollow" target="_blank"&gt;http://www.36kr.com/p/200787.html?vt=0&lt;/a&gt;
Khan Academy: &lt;a href="http://www.36kr.com/p/168454.html" rel="nofollow" target="_blank"&gt;http://www.36kr.com/p/168454.html&lt;/a&gt;
Coursera: &lt;a href="http://www.36kr.com/p/200201.html" rel="nofollow" target="_blank"&gt;http://www.36kr.com/p/200201.html&lt;/a&gt;
Knewton: &lt;a href="http://www.36kr.com/p/52915.html" rel="nofollow" target="_blank"&gt;http://www.36kr.com/p/52915.html&lt;/a&gt;
Treehouse: &lt;a href="http://www.36kr.com/p/173397.html" rel="nofollow" target="_blank"&gt;http://www.36kr.com/p/173397.html&lt;/a&gt;
Udacity: &lt;a href="http://www.36kr.com/p/163443.html" rel="nofollow" target="_blank"&gt;http://www.36kr.com/p/163443.html&lt;/a&gt;
Lumosity: &lt;a href="http://www.36kr.com/p/147467.html" rel="nofollow" target="_blank"&gt;http://www.36kr.com/p/147467.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;国内的传课、爱海豚一般，多贝尚可。&lt;/p&gt;

&lt;p&gt;找人开发类似网站的成本为多少？预算 10 万左右，社区里有没有人愿意接单？&lt;/p&gt;</description>
      <author>kevinhua</author>
      <pubDate>Thu, 17 Jan 2013 21:33:02 +0800</pubDate>
      <link>https://ruby-china.org/topics/8151</link>
      <guid>https://ruby-china.org/topics/8151</guid>
    </item>
    <item>
      <title>oEmbed China Media Provider</title>
      <description>&lt;p&gt;OEmbed-it，没试过，不知道好不好用。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/oneplace/OEmbed-it" rel="nofollow" target="_blank"&gt;https://github.com/oneplace/OEmbed-it&lt;/a&gt;&lt;/p&gt;</description>
      <author>kevinhua</author>
      <pubDate>Wed, 05 Dec 2012 10:13:09 +0800</pubDate>
      <link>https://ruby-china.org/topics/7321</link>
      <guid>https://ruby-china.org/topics/7321</guid>
    </item>
    <item>
      <title>大家来一起坚持 ** 自由开放的互联网 **</title>
      <description>&lt;p&gt;大家来一起坚持&lt;strong&gt;自由开放的互联网&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.freeandopenweb.com/?utm_source=freeandopen&amp;amp;utm_medium=hp&amp;amp;utm_campaign=fo-p2-hp#loc=3/8.0000/22.0000" rel="nofollow" target="_blank"&gt;http://www.freeandopenweb.com/?utm_source=freeandopen&amp;amp;utm_medium=hp&amp;amp;utm_campaign=fo-p2-hp#loc=3/8.0000/22.0000&lt;/a&gt;&lt;/p&gt;</description>
      <author>kevinhua</author>
      <pubDate>Tue, 04 Dec 2012 21:26:41 +0800</pubDate>
      <link>https://ruby-china.org/topics/7305</link>
      <guid>https://ruby-china.org/topics/7305</guid>
    </item>
    <item>
      <title>数据可视化即报告自动生成</title>
      <description>&lt;p&gt;不知道社区里有没有&lt;strong&gt;数据可视化即报告自动生成&lt;/strong&gt;领域的高手。&lt;/p&gt;</description>
      <author>kevinhua</author>
      <pubDate>Fri, 30 Nov 2012 10:19:12 +0800</pubDate>
      <link>https://ruby-china.org/topics/7212</link>
      <guid>https://ruby-china.org/topics/7212</guid>
    </item>
    <item>
      <title>Quake 的一篇文章：介绍好用的 Faraday</title>
      <description>&lt;p&gt;Quake 的一篇文章：&lt;/p&gt;

&lt;p&gt;60 行代码实现分享到微博，QQ 空间，豆瓣 - 介绍好用的 Faraday&lt;/p&gt;

&lt;p&gt;博文地址：&lt;/p&gt;

&lt;p&gt;&lt;a href="http://quake.iteye.com/blog/1610238" rel="nofollow" target="_blank"&gt;http://quake.iteye.com/blog/1610238&lt;/a&gt;&lt;/p&gt;</description>
      <author>kevinhua</author>
      <pubDate>Sat, 17 Nov 2012 10:51:33 +0800</pubDate>
      <link>https://ruby-china.org/topics/6831</link>
      <guid>https://ruby-china.org/topics/6831</guid>
    </item>
    <item>
      <title>买了票，但大会两天因故不能出席，赠送给第一个回复者</title>
      <description>&lt;p&gt;买了票，但大会两天因故不能出席，赠送给&lt;strong&gt;第一个回复者&lt;/strong&gt;&lt;/p&gt;</description>
      <author>kevinhua</author>
      <pubDate>Tue, 06 Nov 2012 21:45:52 +0800</pubDate>
      <link>https://ruby-china.org/topics/6574</link>
      <guid>https://ruby-china.org/topics/6574</guid>
    </item>
    <item>
      <title>常见的 JavaScript MVC 框架</title>
      <description>&lt;p&gt;翻译比较粗糙，原汁原味的英文请参考：&lt;a href="http://codebrief.com/2012/01/the-top-10-javascript-mvc-frameworks-reviewed/" rel="nofollow" target="_blank" title=""&gt;The Top 12 Javascript MVC Frameworks Reviewed&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;在过去的几个月里，我一直在搜寻完美的 JavaScript MVC 框架。我希望这个框架抽象和各项特性都比较合理。最终我筛选出了一些框架，下面是对每个框架的简明扼要的概括。在最后，我会告诉你我自己的最终决策。&lt;/p&gt;

&lt;p&gt;特别地，下面四个特性对于我来说非常重要：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;界面绑定 (UI Bindings) - 不仅是模板层的绑定，我希望构成基础的模型发生改变时，可以自动更新视图层 (即模型层和视图层的绑定)。&lt;/li&gt;
&lt;li&gt;视图排版 (Composed Views) - 与所有软件开发者一样，我享受创建模块化、可复用的代码。基于这个原因，在编写界面时，我希望可以对视图进行排版 (最好在模板层面)。应该提供丰富的视图层次结构。一个很好的例子就是可以复用的分页 Widget。&lt;/li&gt;
&lt;li&gt;页面展现层 (Web Presentation Layer) - 我们是在编写网页应用，我希望框架提供原生 - 样式的 Widgets。没有理由每个框架都创建自己的布局管理器。HTML 和 CSS 已经足够，框架必须围绕这一概念。&lt;/li&gt;
&lt;li&gt;兼容其它 (Plays Nicely With Others) - 我们需要面对这一点，jQuery 令人震惊。我不希望某个框架集成 jQuery 的一个子集，我希望框架推荐使用 jQuery 本身。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="竞争者 (The Contenders)"&gt;竞争者 (The Contenders)&lt;/h3&gt;
&lt;p&gt;下表是支持上述 4 个特性的 JavaScript MVC 框架：&lt;/p&gt;

&lt;p&gt;&lt;img src="//l.ruby-china.com/photo/70d120c5ef23288953bd56bf3ce91e61.png" title="" alt=""&gt;&lt;/p&gt;</description>
      <author>kevinhua</author>
      <pubDate>Sat, 15 Sep 2012 18:33:20 +0800</pubDate>
      <link>https://ruby-china.org/topics/5558</link>
      <guid>https://ruby-china.org/topics/5558</guid>
    </item>
    <item>
      <title>贴两个 Ember.js 和 Rails 结合的教程</title>
      <description>&lt;p&gt;Beginning Ember.js on Rails
&lt;a href="http://www.cerebris.com/blog/2012/01/24/beginning-ember-js-on-rails-part-1/" rel="nofollow" target="_blank"&gt;http://www.cerebris.com/blog/2012/01/24/beginning-ember-js-on-rails-part-1/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ember.js and Rails
&lt;a href="http://www.zhubert.com/blog/2012/04/26/ember-dot-js-and-rails-part-1/" rel="nofollow" target="_blank"&gt;http://www.zhubert.com/blog/2012/04/26/ember-dot-js-and-rails-part-1/&lt;/a&gt;&lt;/p&gt;</description>
      <author>kevinhua</author>
      <pubDate>Sun, 02 Sep 2012 12:35:26 +0800</pubDate>
      <link>https://ruby-china.org/topics/5315</link>
      <guid>https://ruby-china.org/topics/5315</guid>
    </item>
  </channel>
</rss>
