<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>sanvi (sanvi)</title>
    <link>https://ruby-china.org/sanvi</link>
    <description>多大</description>
    <language>en-us</language>
    <item>
      <title>分享下最近做独立开发者的一些经历，小程序上线碰到的一些坑</title>
      <description>&lt;p&gt;上篇文章主要是说我怎么把一个想法变成产品，这几天产品算正式上线了，中间还有一些波折，如果有想做开发做独立开发者的同学，希望这篇文章能给你一些帮助。如果你想了解怎么把想法变成产品，那么可以看下上篇文章。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ruby-china.org/topics/39833" rel="nofollow" target="_blank"&gt;https://ruby-china.org/topics/39833&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="先介绍下我的项目"&gt;先介绍下我的项目&lt;/h2&gt;&lt;h3 id="项目是做什么的"&gt;项目是做什么的&lt;/h3&gt;
&lt;p&gt;我希望打造一款全网平台的圈子小程序，给到一个小的 KOL（你可以理解粉丝在 10 万以内的内容运营者）使用，目前已经上线了微信平台，可以直接搜索&lt;strong&gt;说两句圈子&lt;/strong&gt;，或者扫描下面二维码使用。&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2020/b714ccbd-7c29-4e7b-bc31-79a63b0975d2.jpg!large" title="" alt=""&gt;&lt;/p&gt;
&lt;h3 id="为什么叫说两句"&gt;为什么叫说两句&lt;/h3&gt;
&lt;p&gt;我认为每个人的私域流量都是有价值的，每个人应该有发声的地方，让所有关注我的人都能听到，而不是在单一平台多次发声。所以大家安静点，让我来&lt;strong&gt;说两句&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="和微信圈子和知识星球有何不一样"&gt;和微信圈子和知识星球有何不一样&lt;/h3&gt;
&lt;p&gt;目前的功能看来，并无太大的不同，未来还会在上头条小程序，并且后续会支持独立小程序，让每个人 KOL 拥有自己的圈子小程序&lt;/p&gt;
&lt;h3 id="你是独立开发还是有团队"&gt;你是独立开发还是有团队&lt;/h3&gt;
&lt;p&gt;因为我本身有 13 年的研发经验，是全栈，也有相应的产品经验，目前暂时还不需要团队来帮忙，觉得 UI 丑的同学，这个我真没办法。在后面后面有设计师能提供指导或帮助前，忍忍&lt;/p&gt;
&lt;h3 id="你希望这里找谁"&gt;你希望这里找谁&lt;/h3&gt;
&lt;p&gt;如果你感兴趣，希望作为早期种子用户，欢迎联系我，我拉你进种子用户群。&lt;/p&gt;
&lt;h2 id="分享一些经历"&gt;分享一些经历&lt;/h2&gt;
&lt;p&gt;上次已经分享了这个项目如何从 0 到 1 产生的，那么现在说下中间碰到的一些问题。&lt;/p&gt;
&lt;h3 id="上线问题"&gt;上线问题&lt;/h3&gt;
&lt;p&gt;作为一款社区型小程序，一开始碰到的问题不是流量，而是各种资质问题。隔壁电鸭的各位分享了一些经验，在我之前的帖子里。&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2020/5627ca6f-0546-4437-a8a8-99b6636e5beb.png!large" title="" alt=""&gt;
&lt;img src="https://l.ruby-china.com/photo/2020/b8fafd81-53e1-4cbe-a7db-0fbb70cb31cd.png!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;这里我说下我碰到的几个问题&lt;/p&gt;
&lt;h4 id="公司主体的问题"&gt;公司主体的问题&lt;/h4&gt;
&lt;p&gt;我从 4 月就注册了一家公司，疫情期间，公司注册一直拖我拖到了 5 月，前两周才下来。因为一直拖着，我又不能等着他，所以只能先用个人的身份申请了域名和进行备案，然后用个人小程序先进行开发。等公司下来后，需要把域名备案迁移到公司主体，然后在申请一个公司主体的小程序，然后才能提交审核。这期间各种漫长的等待，但你没任何办法。&lt;/p&gt;
&lt;h4 id="内容型小程序审核问题"&gt;内容型小程序审核问题&lt;/h4&gt;
&lt;p&gt;因为有 UGC 内容的产生，所以审核会比一般的小程序长，一般是先提交给微信进行审核，因为第一次提交，所以这里需要 1-7 天以内，我等了 3 天。然后会进入二次审核。再次 7 天预警。&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2020/030bb0e9-a4d3-454c-a802-5a63e32a3074.jpg!large" title="" alt=""&gt;&lt;/p&gt;
&lt;h4 id="内容审查问题"&gt;内容审查问题&lt;/h4&gt;
&lt;p&gt;之前分享过一篇敏感词的实现的问题，但我太 naive 了，只对了帖子和文章对了敏感词检查，万万没想到官方人员钓鱼执法。然后就给我警告了。&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2020/1a0526e5-61ba-49c5-8647-4767fd5b32d3.jpg!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;我进去看了下原因&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2020/e228d420-49a7-4577-b5e6-a80f32945ac6.jpg!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;果然，我还是太天真了。他们居然在创建圈子的时候开车。&lt;/p&gt;

&lt;p&gt;无奈之下，只好把所有接口涉及到文本提交的地方都加上敏感词过滤，然后后台接入了微信官方的内容审查接口，目前所有涉及文本和图片的地方，都会做检测。&lt;/p&gt;

&lt;p&gt;为了做测试，我专门去找了明日花老师的图片来进行测试，嗯，基本上都提交不了。&lt;/p&gt;
&lt;h3 id="引流问题"&gt;引流问题&lt;/h3&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;另外要说的是头条，头条的好处在于他用户量大，基于推荐，所以文章有一定的概率被推荐，我的那篇敏感词的文章就有 13 万的曝光，带来了不少粉丝关注。并有机会被拉入官方的创作培养群，学习了一些写作技巧和平台规则，目前看来是一个相对有空间的渠道。&lt;/p&gt;

&lt;p&gt;大家有兴趣可以直接在上面平台搜”卢灿伟“，全网同名，大家可能会问，为什么不开星球，目前对我来说我还没有那么干的干货，镰刀太小了。&lt;/p&gt;
&lt;h2 id="接活的情况"&gt;接活的情况&lt;/h2&gt;
&lt;p&gt;说完理想，在说下现实，项目不赚钱的情况下，总是要恰饭的吧。&lt;/p&gt;

&lt;p&gt;除了 4 月接了一单外卖平台运营相关的活外，后面就不是特别顺利。&lt;/p&gt;

&lt;p&gt;碰到甲方都非常奇怪，需求也不给，说要做什么东西，具体要文档也给不出，就画了张图，很难聊下去。&lt;/p&gt;

&lt;p&gt;还有就是这种，后面更难听的话我就不截取了，感觉不是很尊重乙方，因为疫情原因，所以都觉得自己是上帝在赏吃的吗？&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2020/75601e1c-e8ec-456b-a544-9c9fdb1a653b.jpg!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;后来我找了一个大哥聊了下，他建议我先谈价格再谈需求，如果对方根本无意用合理的价格跟你沟通，也没必要浪费大家时间了。&lt;/p&gt;
&lt;h2 id="最后"&gt;最后&lt;/h2&gt;
&lt;p&gt;再次强调，无论是对项目感兴趣，还是希望找短期开发，欢迎联系我。&lt;/p&gt;</description>
      <author>sanvi</author>
      <pubDate>Thu, 28 May 2020 18:25:36 +0800</pubDate>
      <link>https://ruby-china.org/topics/39915</link>
      <guid>https://ruby-china.org/topics/39915</guid>
    </item>
    <item>
      <title>敏感词过滤实现</title>
      <description>&lt;p&gt;了解我的小伙伴都知道我最近自己在做一个社区的小程序，希望能帮助大家能无代码创建一个社区小程序。社区里内容是很重要的一块，但往往很多时候会有人来发一些开车（麻烦前面右拐 P 站，谢谢）内容，所以最基本的防控还是要有的。&lt;/p&gt;

&lt;p&gt;作者本人独立开发者，接各种前后端外包、兼职工作。无论是工作、技术交流、项目讨论，都欢迎加我进行交流&lt;/p&gt;
&lt;h2 id="词库的准备"&gt;词库的准备&lt;/h2&gt;
&lt;p&gt;首先我们可以从网上下载词库，不过我下载的词库有些时候了，谁有新版的词库也可以告知我一下，我好更新下。&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2020/5a3d9eb4-0850-4748-95a3-164de8e8848f.png!large" title="" alt=""&gt;&lt;/p&gt;
&lt;h2 id="DFA算法"&gt;DFA 算法&lt;/h2&gt;
&lt;p&gt;一般想到的是遍历匹配，但这样效率太差了。另外一种是正则表达式，直观上感觉也很差。&lt;/p&gt;

&lt;p&gt;查了下资料，比较简单容易实现的是 DFA 算法。DFA（Deterministic Finite Automaton，即确定有穷自动机。其原理为：有一个有限状态集合和一些从一个状态通向另一个状态的边，每条边上标记有一个符号，其中一个状态是初态，某些状态是终态。但不同于不确定的有限自动机，DFA 中不会有从同一状态出发的两条边标志有相同的符号。&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2020/6505e535-dd70-4028-b4a0-ea155d6069cd.png!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;因为只有状态的变化，没任何运算，在效率上还是相对比较可观，要说唯一的缺点嘛，那应该就是比较吃内存，因为相当于你需要把一整棵树都存在内存上。&lt;/p&gt;

&lt;p&gt;就上图来说，通过查找，一步步从 S 查找到 P。&lt;/p&gt;
&lt;h3 id="例子"&gt;例子&lt;/h3&gt;
&lt;p&gt;假设我们词库里有以下 2 个敏感词：成人论坛、成人电影，首先我们要建立一个这样的结构。&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2020/5bb7aca2-468c-4d1a-aa4b-8e7577e13f9b.png!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;这样就能大幅度的减少我们检索的范围了。那我们怎么判断一个敏感词的检测已经结束了呢，那就需要加一个标志位来确认。&lt;/p&gt;
&lt;h3 id="具体流程"&gt;具体流程&lt;/h3&gt;&lt;h4 id="1.清洗数据"&gt;1.清洗数据&lt;/h4&gt;
&lt;p&gt;假设我们有一段 如下内容&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;*-`J情成&amp;amp;^人电影在**$#线观看
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个时候我们第一步是对内容做清洗，把特殊的标点符号去除，变成纯文字&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;J情成人电影在线观看
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="2.字符穷举"&gt;2.字符穷举&lt;/h4&gt;
&lt;p&gt;首页我们对上面的文字进行穷举，列出我们需要检测的所有的可能性&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;J
J情
J情成
J情成人
J情成人电
J情成人电影
J情成人电影在
J情成人电影在线
J情成人电影在线观
J情成人电影在线观看
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="检测"&gt;检测&lt;/h4&gt;
&lt;p&gt;前两次检测不出来，在第三次，字符”成“命中了上图的关键字。&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2020/cd5db033-58ea-405f-9d61-cfc0ab5aa6f5.png!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;那我们就再次把当前检测的节点从”成“换成了”人“这个节点，以此类推。&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2020/88be7799-d070-4708-92df-226f99d9ba68.png!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;下面附上源码的实现&lt;/p&gt;
&lt;h2 id="源码"&gt;源码&lt;/h2&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;require “set"
require “pry”
require ‘active_support/core_ext’

Word = Struct.new(:is_end, :value)

class FilterSensitiveWord
  attr_accessor :words
  MIN_MATCH_TYPE = 1
  MAX_MATCH_TYPE = 2

  def initialize()
    @hash = Hash.new
  end

  def load(file_path)
    @words = Set[]
    f = File.open(file_path, “r”)
    f.each_line do |line|
      @words.add(line)
    end
    f.close
    to_hash(@words)
  end

  def to_hash(words)
   words.map do |word|
      word_hash = @hash
      word.strip.chars.to_a.map.with_index do |c,index|
        if word_hash[c].blank?
          if word.strip.length - 1 == index
            word_hash[c] = Word.new(true,Hash.new)
          else
            word_hash[c] = Word.new(false,Hash.new)
            word_hash = word_hash[c].value
          end
        else
          word_hash = word_hash[c].value
        end
      end
    end
    @hash
  end

  def check_sensitive_word(txt, index, match_tpye) 
    match_flag = 0
    word_hash = @hash
    flag = false
    txt.each do |w|
      if word_hash[w].blank?
        break
      else
        match_flag = match_flag + 1
        if word_hash[w].is_end
          flag = true
          if match_tpye == MIN_MATCH_TYPE
            break
          end
        else 
          word_hash = word_hash[w].value
        end
      end
    end
    unless flag
      match_flag = 0
    end
    match_flag
  end


  def check(text,match_tpye)
    words = []
    skip_len = 0
    text = text.strip.gsub(/[`~!@#$^&amp;amp;*()=|{}':;',\\\[\]\.&amp;lt;&amp;gt;\/?~！@#￥……&amp;amp;*（）——|{}【】'；：""'。，、？]/,'')
    if text.present?
      text.chars.each_with_index do |c, i| 
        if skip_len &amp;gt; i
          next
        end
        len = check_sensitive_word(text.chars.drop(i), i, match_tpye)
        if len &amp;gt; 0
          words.push text[i, len]
          skip_len = i + len - 1
        end 
      end
    end

    words
  end

end


$filter_sensitive_word = FilterSensitiveWord.new()
$filter_sensitive_word.load("./words/广告.txt")
$filter_sensitive_word.load("./words/政治类.txt")
$filter_sensitive_word.load("./words/涉枪涉爆违法信息关键词.txt")
$filter_sensitive_word.load("./words/色情类.txt")
puts $filter_sensitive_word.check("*-`J情成&amp;amp;^人电影在**$#线观看",1)

&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="总结"&gt;总结&lt;/h2&gt;
&lt;p&gt;总的来说，除了内存的问题，性能上没任何问题。&lt;/p&gt;

&lt;p&gt;在 2020 年，这种检测方式显然很落后，但如果作为第一层过滤，效果还是蛮可观的。进来的内容，最好的方式肯定是基于深度学习和 NLP 自然语义分析，这些可以去调各大厂云平台的接口。最后一层还是人工，前端举报和后端抽查和内容审核。&lt;/p&gt;
&lt;h2 id="参考资料"&gt;参考资料&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;java 敏感词之 DFA 算法 (Tire Tree 算法)&lt;/li&gt;
&lt;li&gt;java 实现敏感词过滤（DFA 算法）&lt;/li&gt;
&lt;/ul&gt;</description>
      <author>sanvi</author>
      <pubDate>Tue, 12 May 2020 16:59:31 +0800</pubDate>
      <link>https://ruby-china.org/topics/39859</link>
      <guid>https://ruby-china.org/topics/39859</guid>
    </item>
    <item>
      <title>各位我回来了，这次我做了一款社区小程序</title>
      <description>&lt;h2 id="起因"&gt;起因&lt;/h2&gt;
&lt;p&gt;在去年底做了一场手术后，我就在想，长期高强度工作给我带来了什么？想了半天只得到一个结论，就是相对安稳的生活。&lt;/p&gt;

&lt;p&gt;开始把我多年前注册的公众号搬了出来，开始自己写一些文章，主要是针对目前外面比较火的一些新产品做一些个人解读，一是为了能让自己更叫了解产品和商业（毕竟自己是技术出身），另外一方面是希望能找到将来能做的事情。还有就是能多认识些朋友。&lt;/p&gt;

&lt;p&gt;断断续续大概也写了 20 篇，粉丝并未有太大的增长，虽说是想多认识些朋友，不过来去还是朋友圈的支持。知乎上的情况会稍微好点。用户大概就是微信的 10 倍。这也能看出来微信公众号的流量红利基本上已经没太多了。&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2020/30eeb22c-1bf1-4337-9665-33ca2894719a.png!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;并且年底的时候，有一些朋友希望让我帮他们介绍工作，包括我自己也想是不是能换一份稍微轻松点的工作，发现最大的问题在于，当你工作到一定年限，你所能做的选择就越来越少。&lt;/p&gt;

&lt;p&gt;社交认证是非常重要的一个东西，我有个朋友投某厂的一个岗位，结果石沉大海。后面找到我，我找了一个内部的朋友内推，顺利入职了。&lt;/p&gt;

&lt;p&gt;我认为每个人的私域流量都非常有价值，但微信朋友圈其实是基于私密的社交距离。比如你的朋友 A 在招人，你的朋友 B 想换工作，但你不知道。所以需要有一个秘密基地，大家经常能聚的地方。这样才能有效的分享情报。&lt;/p&gt;
&lt;h2 id="执行"&gt;执行&lt;/h2&gt;
&lt;p&gt;“一千个人眼度里有一千个哈姆雷特”&lt;/p&gt;

&lt;p&gt;如果你无法描述清楚你的产品，那么就做出来，告诉他们，你的产品长这样。&lt;/p&gt;

&lt;p&gt;第一件事，把你的产品具象化，比如你的产品长啥样，流程是什么。当然你可以直接从纸上画出来，不过我个人还是推荐&lt;strong&gt;figma&lt;/strong&gt;，虽然最终界面可能跟界面会有一些出入，但原型最主要是的给你理清流程。&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2020/1ffdd9bf-07c1-4fa9-98bc-13314902c96d.png!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;然后用&lt;strong&gt;mindnode&lt;/strong&gt;大概写了一下所包含的功能点，这里主要是想让你确认你的产品 MVP 到底是怎么样？不要把你的产品想得太大，没有什么产品是能一步到位到 10 的，都是一步步迭代过来的。虽然我上面写的我也感觉多了，但总比没局限的扩散好。&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2020/b90a3587-4ce6-4823-94d5-dd1781a500c9.png!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;在确认后，就是开始编码的工作了，这里的东西可能就比较偏向技术化的东西，不太适合在这篇文章里说，会专门在写一篇碰到的问题和解决的思路，提供大家思考。&lt;/p&gt;
&lt;h2 id="困难"&gt;困难&lt;/h2&gt;
&lt;p&gt;我觉得独立开发者最困难的并不是做上面的各种事情，最困难的反而是在精力的分配上。&lt;/p&gt;

&lt;p&gt;比较关键的点在于，你没收入，所以你得想办法去创造收入，你需要分出一部分的时间去找有收入的事情做，像这个项目，其实整个 4 月都处于停滞状态，因为我接了一个外卖运营的活，这个在我另外一个文章有讲到。&lt;/p&gt;

&lt;p&gt;然后你需要平衡好陪伴家人的时间，因为以前是带薪的，现在是无薪的，肯定有区别。哈哈哈~~&lt;/p&gt;

&lt;p&gt;还有就是你会多出来很多乱七八糟的事情，比如小程序资质的问题、企业身份的问题、备案、服务器等，因为在家时间久，所以也会开始自己弄饭吃等。这些事情会进一步开始压迫你的时间。&lt;/p&gt;

&lt;p&gt;所幸的是，你第二天不用早起。但这也会让你无法管控自己的时间，目前我的做法是电脑上装个&lt;strong&gt;Timing&lt;/strong&gt;来保证自己每天的工作时间。&lt;/p&gt;
&lt;h2 id="失败"&gt;失败&lt;/h2&gt;
&lt;p&gt;最初我是希望给这些有影响力的小 B 一个创建社区的平台，但第一个版本功能太薄弱了，对于目前市场上建小程序的平台来说，他们的功能太丰富了。并且对于社区小程序上架来说，限制太多了，跟以往弄个备案网站就能开不一样，第一版对外内测后，效果并不好。我所认识的小 B 们根本没能力搞掂这些事情。大 B 们更倾向自建或者用建站平台，没太明显的差异化。&lt;/p&gt;

&lt;p&gt;后面我就决定转向面向 C 端，但保留 B 端建站能力。任何人都可以创建社区，并后续希望能提供可以自定义化社区的能力，除了产品结构调整外，也需要考虑上架资质，目前小程序还无法上线，在做一些上架资质的申请，有兴趣的小伙伴可以加我，我给你们体验版尝试。&lt;/p&gt;
&lt;h2 id="最后"&gt;最后&lt;/h2&gt;
&lt;p&gt;为什么我要写这篇文章，主要有几点&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;毕竟我还要恰饭，如果有社区小程序定制的项目开发或者其他方面开发，都可以联系我，毕竟是 12 年经验的老码农，也有过日活 50 万以上产品的研发经验&lt;/li&gt;
&lt;li&gt;毕竟是独立项目，所以希望在发布前能找一些感兴趣的&lt;strong&gt;种子用户&lt;/strong&gt;进行测试，帮忙抓抓 Bug 或者交流看法，我会拉你进群&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;最后的最后，如果你对我或者项目感兴趣，无论是产品方向，还是技术方面，或者其他方面，都欢迎交流讨论。&lt;/p&gt;

&lt;p&gt;希望在经营社区的同时，也能经营好自己。&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2020/4e37e2e7-e73a-4c1f-9257-485bb75d2ba1.jpg!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;PS. 最后放几张产品图
&lt;img src="https://l.ruby-china.com/photo/2020/2d68c28e-d1df-4b7d-8333-576f6078a70b.png!large" title="" alt=""&gt;
&lt;img src="https://l.ruby-china.com/photo/2020/631b1aed-b105-4570-8361-cac817317c99.png!large" title="" alt=""&gt;
&lt;img src="https://l.ruby-china.com/photo/2020/45ad2116-bfa4-4f98-973f-eab1393325f8.png!large" title="" alt=""&gt;&lt;/p&gt;</description>
      <author>sanvi</author>
      <pubDate>Tue, 05 May 2020 23:19:46 +0800</pubDate>
      <link>https://ruby-china.org/topics/39833</link>
      <guid>https://ruby-china.org/topics/39833</guid>
    </item>
    <item>
      <title>我需要组装一个复杂的对象，不知道有没更好的实现方式</title>
      <description>&lt;p&gt;hi，各位，我打算组装一个这样的对象，Template 里面一个模板，含 header 跟 body，body 其实是一个 Card 的数组，Card 的 new 如下图那样
不知道有没更好的实现方式&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="sr"&gt;//&lt;/span&gt;&lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Card&lt;/span&gt;
  &lt;span class="nb"&gt;attr_accessor&lt;/span&gt; &lt;span class="ss"&gt;:url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:style&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:id&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="nb"&gt;instance_variable_set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"@&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&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;span class="k"&gt;end&lt;/span&gt;

&lt;span class="sr"&gt;//&lt;/span&gt;&lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Header&lt;/span&gt;
  &lt;span class="nb"&gt;attr_accessor&lt;/span&gt; &lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:menu&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:icon&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="nb"&gt;instance_variable_set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"@&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&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;span class="k"&gt;end&lt;/span&gt;
&lt;span class="sr"&gt;//s&lt;/span&gt;&lt;span class="n"&gt;tyle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Style&lt;/span&gt;
  &lt;span class="nb"&gt;attr_accessor&lt;/span&gt; &lt;span class="ss"&gt;:margin_top&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:margin_right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:margin_bottom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:margin_left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:background&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="nb"&gt;instance_variable_set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"@&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&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;span class="k"&gt;end&lt;/span&gt;

&lt;span class="sr"&gt;//&lt;/span&gt;&lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Template&lt;/span&gt;
  &lt;span class="nb"&gt;attr_accessor&lt;/span&gt; &lt;span class="ss"&gt;:header&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:body&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="nb"&gt;instance_variable_set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"@&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&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;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_card&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@body&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="no"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
    &lt;span class="vi"&gt;@body&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;card&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="sr"&gt;//&lt;/span&gt;&lt;span class="n"&gt;这里是组装对象&lt;/span&gt;

&lt;span class="n"&gt;nameView&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;root&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/user.json"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;&lt;span class="ss"&gt;:type&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"NameItemCard"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:style&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:margin_top&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"nameCard"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;itemView&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;root&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/setting_item.json"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;&lt;span class="ss"&gt;:type&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"ItemDividerCard"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="ss"&gt;:style&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:margin_top&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ss"&gt;:id&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"itemCard"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;buttonView&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;root&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/setting_button.json"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;&lt;span class="ss"&gt;:type&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"MatchButtonCard"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:style&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:margin_top&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ss"&gt;:id&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"btnLogout"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:title&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"我的"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:icon&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"ic_tab_me_normal"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:header&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;add_card&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nameView&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;add_card&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;itemView&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;add_card&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buttonView&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;</description>
      <author>sanvi</author>
      <pubDate>Thu, 05 Nov 2015 17:29:43 +0800</pubDate>
      <link>https://ruby-china.org/topics/27970</link>
      <guid>https://ruby-china.org/topics/27970</guid>
    </item>
    <item>
      <title>[上海] 奢圈招聘 Ruby 工程师</title>
      <description>&lt;h3 id="公司介绍"&gt;公司介绍&lt;/h3&gt;
&lt;p&gt;WHOSV 是 VIP 邀请制的全新移动社交平台，致力于为来自世界各地在中国的新贵人士提供与众不同优质可靠的社交模式，一个专属于 1% 的准社交网络。 
作为一个以封闭式为主的 SNS 在线的私人俱乐部，WHOSV（奢圈）关注的用户是生长和生活在中国一线城市，有逻辑化生活方式的都市新贵。 
WHOSV 会员有相似的背景及国际化的生活方式。会员通过 WHOSV（奢圈）体验个性化的旅行、派对、约会。尊享城中最好的餐厅、酒店、酒吧等独家品牌商户的定制服务。会员可以通过 WHOSV（奢圈）国际社区拓展新人脉、新商机、新前景。&lt;/p&gt;
&lt;h3 id="职位要求"&gt;职位要求&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;两年以上的 Ruby 项目经验（有能力可以无视）&lt;/li&gt;
&lt;li&gt;熟悉 Web 开发技术，追去简介优雅的代码&lt;/li&gt;
&lt;li&gt;具备扎实的面向对象语言功底，有 Java，PHP, Python 等语言开发经验的优先考虑&lt;/li&gt;
&lt;li&gt;具备良好的团队意识和协作精神，有较强的沟通能力&lt;/li&gt;
&lt;li&gt;熟练使用 Mysql 和一种 nosql(redis、mongodb)&lt;/li&gt;
&lt;li&gt;会使用 git 和 git flow 进行代码控制&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="待遇"&gt;待遇&lt;/h3&gt;
&lt;p&gt;8-15k&lt;/p&gt;
&lt;h3 id="我们会用到的一些工具"&gt;我们会用到的一些工具&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;目前使用进行代码托管 &lt;a href="https://bitbucket.org/" rel="nofollow" target="_blank" title=""&gt;bitbucket&lt;/a&gt; ，之后后会使用 gitlab&lt;/li&gt;
&lt;li&gt;Tower(项目管理) &amp;amp;&amp;amp; Redmine（wiki 和 bug 追踪）&lt;/li&gt;
&lt;li&gt;SourceTree&lt;/li&gt;
&lt;li&gt;QQ（妹纸们都用 QQ）&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="加分项"&gt;加分项&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;熟悉常用的网络安全、负载均衡等手段，能基于云平台构建出可靠、有扩展性的 RESFul 服务&lt;/li&gt;
&lt;li&gt;对新技术有很强的好奇心和学习能力&lt;/li&gt;
&lt;li&gt;参与过开源项目&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="其他信息"&gt;其他信息&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;我们也招 Android/IOS，欢迎推荐或者自荐&lt;/li&gt;
&lt;li&gt;不定期的会组织 SPA，组织旅游，高档饭店聚餐，KTV 等活动。还有一些其他的员工福利，美容卡等。对于优秀的员工会给予期权 或者 适当的奖金作为奖励 &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;请发邮件到：sanvi@whosv.com&lt;/p&gt;</description>
      <author>sanvi</author>
      <pubDate>Wed, 20 Aug 2014 12:48:03 +0800</pubDate>
      <link>https://ruby-china.org/topics/21135</link>
      <guid>https://ruby-china.org/topics/21135</guid>
    </item>
    <item>
      <title>你们的 finder 会不会升级到 mavericks 不能使用</title>
      <description>&lt;p&gt;一直 crash，非常郁闷&lt;/p&gt;

&lt;p&gt;升级上来发现 java 给干掉了。。。也好像吐槽&lt;/p&gt;

&lt;p&gt;有求解救方案&lt;/p&gt;</description>
      <author>sanvi</author>
      <pubDate>Sun, 10 Nov 2013 10:40:50 +0800</pubDate>
      <link>https://ruby-china.org/topics/15428</link>
      <guid>https://ruby-china.org/topics/15428</guid>
    </item>
    <item>
      <title>我们在上海待 2 周，希望能跟上海的创业者们交流下</title>
      <description>&lt;p&gt;hi，各位我们来到上海了！刚参加完 RubyConf 大会跟大家交流收获非常多。&lt;/p&gt;

&lt;p&gt;这趟过来主要是想跟上海的创业者们聊聊，开拓下思路&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;关于信+&lt;/strong&gt;
网站： &lt;a href="http://xin.io" rel="nofollow" target="_blank"&gt;http://xin.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;信 + 是一个针对移动端的客服工具，我们提供第三方的 SDK 让你在你的 APP 里面嵌入客服界面，让你几乎零成本使用客服功能以满足你日益增多的咨询量。具体演示可以参考网站的视频&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;关于我们&lt;/strong&gt;
现在我们团队有 4 个人，2 个技术，1 个产品，1 个设计。这趟来上海的是我跟我的搭档 Harry。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;技术经历&lt;/strong&gt;
我是高一辍学后通过一些培训进入互联网的圈子，第一份工作就以 Java 为主，后来在 08 年底 Android 横空出现，左 Java 的我果断就做起了 Android 开发，也是那时开始走非主流技术路线，一方面 Java 厌恶了传统的开发方式，开始尝试一些可以跟 Java 结合的技术，比如 groovy on grails，后来觉得 grails 的模板引擎不给力，就开始尝试原生的 Java 框架 Play，Play 是个非常不错的框架，感觉完全 Rails 式的开发，后来在第一次尝试创业时觉得太笨重抛弃了 Java 然后开始接触 Ruby&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;创业经历&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;第一个项目&lt;/strong&gt;
10 年是我第一次有创业的想法，当时想做的是一个外卖的搜索引擎，因为之前在上海的一个互联网公司是做餐饮有关项目，当时在 gurudigger 上讨论非常热烈，可以参考该项目链接
&lt;a href="http://gurudigger.com/ideas/281" rel="nofollow" target="_blank"&gt;http://gurudigger.com/ideas/281&lt;/a&gt;，这个项目是 Java 做的，一个人的能力相当的有限，最后因身体原因无力支撑这个项目而结束&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;第二个项目&lt;/strong&gt;
第二个项目是书愿网，当时生病的时候在医院想出来的一个 idea，待医院真的很无聊，希望能借点书来看，所以了有&lt;a href="http://ibookwish.com" rel="nofollow" target="_blank" title=""&gt;书愿网&lt;/a&gt;,网站虽然现在每天都有人注册，但还是放弃了这个项目，^_^幸运的是给报道了，不过还是改变不了关闭的命运&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;不是创业的项目&lt;/strong&gt;
这个项目非常的有意思，参加深圳的 Startup Weekend，然后想不到说一个什么点子好，就想起每个宅男都会面临的问题，怎么认识女孩子！！！所以就有了开场白的这个项目，其实开场白，就是提供你一些开场话题，然后让你自己跟女生搭讪的 APP，果然是硬需求，Android 跟 IOS 都上线了，在无任何运营的情况下，已经增长到 4 万的用户量了。。。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;现在&lt;/strong&gt;
信 + 这个项目其实是从书愿网衍伸出来的，但是觉得书愿网是否在该做 APP 来在尝试一下，但感觉需要在里面实现一个 IM，后来就把 IM 抽离出来，慢慢的就成为了现在的信+&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;困惑&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;信 + 现在面临的很大问题，因为是小团队的项目，所以面向的客户都是创业型的小团队，他们倾向于不要客服，尽可能用邮件这些非实时的。&lt;/li&gt;
&lt;li&gt;面临着微信（最近微信开放了企业级 API）跟友盟的双面夹击&lt;/li&gt;
&lt;li&gt;信 + 目前现在还未接受任何资金，都是我们自己在撑，虽然之前有投资有意向，但国内的条件，呵呵。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;联系方式&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;邮箱：sanvibyfish@gmail.com&lt;/li&gt;
&lt;li&gt;微信：sanvibyfish&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;最后非常感谢大家能读到这里，我们会在上海待 2 个星期左右，希望上海的创业者可以跟我们多交流下。&lt;/p&gt;</description>
      <author>sanvi</author>
      <pubDate>Sat, 02 Nov 2013 14:16:17 +0800</pubDate>
      <link>https://ruby-china.org/topics/15241</link>
      <guid>https://ruby-china.org/topics/15241</guid>
    </item>
    <item>
      <title>有没更好的写法？</title>
      <description>&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="vi"&gt;@count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="vi"&gt;@app.builds.each&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="vi"&gt;@count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;build&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;/code&gt;&lt;/pre&gt;
&lt;p&gt;ruby 有很多语法糖，但大多数新手都是从写 Rails 一边写 ruby，希望可以大家可以多分享点&lt;/p&gt;</description>
      <author>sanvi</author>
      <pubDate>Mon, 14 Oct 2013 10:31:24 +0800</pubDate>
      <link>https://ruby-china.org/topics/14723</link>
      <guid>https://ruby-china.org/topics/14723</guid>
    </item>
    <item>
      <title>deploy 脚本的问题</title>
      <description>&lt;p&gt;我看到 ruby-china 有这行代码，但是他们用的是同一个 unicorn.rb&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"DEPLOY"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"pre"&lt;/span&gt;
  &lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:deploy_to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"/data/www/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-pre"&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
  &lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:deploy_to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"/data/www/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="c1"&gt;# unicorn.rb 路径&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:unicorn_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;deploy_to&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/current/config/unicorn.rb"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;那么部署 pre 的时候不担心杀掉原本的进程吗？&lt;/p&gt;</description>
      <author>sanvi</author>
      <pubDate>Sat, 28 Sep 2013 16:29:44 +0800</pubDate>
      <link>https://ruby-china.org/topics/14454</link>
      <guid>https://ruby-china.org/topics/14454</guid>
    </item>
    <item>
      <title>Devise 使用远程 API 登录</title>
      <description>&lt;p&gt;首先这是个蛋疼的需求，一般来说，远程做 OAuth2 就行了，但是有很多因素导致（历史遗留问题，老系统等），所以就出现了需要在新的系统上去使用老系统的登录 API&lt;/p&gt;

&lt;p&gt;&lt;img src="//l.ruby-china.com/photo/8f657fa0c286c8515ce076ed1dacb3c6.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;#app/models/user.rb&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;User&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Mongoid&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Document&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Mongoid&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Timestamps&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;ActiveModel&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Validations&lt;/span&gt; &lt;span class="c1"&gt;#required because some before_validations are defined in devise&lt;/span&gt;
  &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;ActiveModel&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Callbacks&lt;/span&gt; &lt;span class="c1"&gt;#required to define callbacks&lt;/span&gt;
  &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;Devise&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Models&lt;/span&gt;
  &lt;span class="n"&gt;devise&lt;/span&gt; &lt;span class="ss"&gt;:remote_authenticatable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:registerable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="ss"&gt;:recoverable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:rememberable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:trackable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:validatable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:authentication_keys&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="c1"&gt;# Setup accessible (or protected) attributes for your model&lt;/span&gt;
  &lt;span class="n"&gt;attr_accessible&lt;/span&gt; &lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:remember_me&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:dept_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:user_id&lt;/span&gt;
  &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ss"&gt;:remember_token&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;首先，你的 User 变成类似如上的格式，把默认的 database_authenticatable 替换成 remote_authenticatable，remote_authenticatable 稍后我们会给出代码&lt;/p&gt;

&lt;p&gt;#lib/remote_authenticatable.rb&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'bcrypt'&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Devise&lt;/span&gt;
  &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Models&lt;/span&gt;
    &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;RemoteAuthenticatable&lt;/span&gt;
      &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Concern&lt;/span&gt;

      &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;BCrypt&lt;/span&gt;


      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;email_required?&lt;/span&gt;
          &lt;span class="kp"&gt;false&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;password_required?&lt;/span&gt;
       &lt;span class="kp"&gt;true&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;ClassMethods&lt;/span&gt;
        &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;serialize_from_session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;
          &lt;span class="n"&gt;resource&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
        &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;serialize_into_session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;user_id&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;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;password_digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;BCrypt&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Password&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="si"&gt;}#{&lt;/span&gt;&lt;span class="no"&gt;Devise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pepper&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:cost&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Devise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stretches&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;


      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;remote_authentication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;authentication_hash&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Your logic to authenticate with the external webservice&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;authentication_hash&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;authentication_hash&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="c1"&gt;# These four parameters are required by the authentication mechanism&lt;/span&gt;
        &lt;span class="c1"&gt;# id/password actually authenticate the user&lt;/span&gt;
        &lt;span class="c1"&gt;# org_id/term_id identify the remote server to perform auth against&lt;/span&gt;

        &lt;span class="vi"&gt;@user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;authentication_hash&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="vi"&gt;@dept_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;authentication_hash&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="ss"&gt;:dept_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="vi"&gt;@password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;authentication_hash&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="ss"&gt;:password&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;authentication_hash&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="ss"&gt;:remember_me&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"1"&lt;/span&gt;
          &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remember_me&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
          &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remember_me&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
        &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remember_token&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="no"&gt;Devise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;friendly_token&lt;/span&gt;


        &lt;span class="c1"&gt;# return false if @id.length &amp;gt; 3&lt;/span&gt;

        &lt;span class="c1"&gt;# Perform remote authentication here&lt;/span&gt;

        &lt;span class="c1"&gt;# The remote auth mechanism returns the user's display name&lt;/span&gt;
        &lt;span class="c1"&gt;# and access control list&lt;/span&gt;
        &lt;span class="c1"&gt;# @name = "Display Name"&lt;/span&gt;
        &lt;span class="c1"&gt;# @acl = "Access Control List"&lt;/span&gt;

        &lt;span class="c1"&gt;# ret = @name != nil and @acl != nil&lt;/span&gt;

        &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'open-uri'&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'nokogiri'&lt;/span&gt;

        &lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Nokogiri&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTML&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"http://xxx.com/login"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;xpath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"//status"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"false"&lt;/span&gt;
          &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;xpath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"//message"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;

        &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@user_id&lt;/span&gt;
        &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emp_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;xpath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"//emp_id"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;
        &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encrypted_password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;password_digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"true"&lt;/span&gt;

      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Strategies&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RemoteAuthenticatable&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Authenticatable&lt;/span&gt;
      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;valid?&lt;/span&gt;
        &lt;span class="kp"&gt;true&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="c1"&gt;#&lt;/span&gt;
      &lt;span class="c1"&gt;# For an example check : https://github.com/plataformatec/devise/blob/master/lib/devise/strategies/database_authenticatable.rb&lt;/span&gt;
      &lt;span class="c1"&gt;#&lt;/span&gt;
      &lt;span class="c1"&gt;# Method called by warden to authenticate a resource.&lt;/span&gt;
      &lt;span class="c1"&gt;#&lt;/span&gt;
      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;authenticate!&lt;/span&gt;

        &lt;span class="c1"&gt;#&lt;/span&gt;
        &lt;span class="c1"&gt;# mapping.to is a wrapper over the resource model&lt;/span&gt;
        &lt;span class="c1"&gt;#&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
          &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="n"&gt;mapping&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user_id&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blank?&lt;/span&gt;
          &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mapping&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;fail&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt;

        &lt;span class="c1"&gt;# validate is a method defined in Devise::Strategies::Authenticatable. It takes&lt;/span&gt;
        &lt;span class="c1"&gt;#a block which must return a boolean value.&lt;/span&gt;
        &lt;span class="c1"&gt;#&lt;/span&gt;
        &lt;span class="c1"&gt;# If the block returns true the resource will be logged in&lt;/span&gt;
        &lt;span class="c1"&gt;# If the block returns false the authentication will fail!&lt;/span&gt;
        &lt;span class="c1"&gt;#&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote_authentication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="n"&gt;success!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resource&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;span class="k"&gt;end&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;当你登录的时候，他会先调用 RemoteAuthenticatable 的 valid?,接着会调用 authenticate!&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 会在本地创建一个User&lt;/span&gt;
  &lt;span class="c1"&gt;# mapping.to is a wrapper over the resource model&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="n"&gt;mapping&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user_id&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blank?&lt;/span&gt;
    &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mapping&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;fail&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后会调用 remote_authentication，RemoteAuthenticatable 的 self 可以理解为 User 本身，在里面我们写了一个 password_digest（PS.这个方法从 devise 里面弄出来得），目的是要把密码重新加密放到本地的数据库里面，接着我们就 call 远程的 API，这里就不用多说了。&lt;/p&gt;

&lt;p&gt;#config/initializers/devise.rb&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'remote_authenticatable'&lt;/span&gt;

&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warden&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strategies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:remote&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Devise&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Strategies&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;RemoteAuthenticatable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;default_strategies&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:scope&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;unshift&lt;/span&gt; &lt;span class="ss"&gt;:remote&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;Warden&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Manager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;serialize_into_session&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="no"&gt;YAML&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="no"&gt;Warden&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Manager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;serialize_from_session&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;yaml&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="no"&gt;YAML&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;yaml&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="no"&gt;Devise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_module&lt;/span&gt; &lt;span class="ss"&gt;:remote_authenticatable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:controller&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:sessions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:route&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;:session&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:routes&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在 devise 的配置加入一个 module，使其工作&lt;/p&gt;

&lt;p&gt;最后，讲得大部分是实现，如果有兴趣深入的同学可以移步
&lt;a href="http://4trabes.com/2012/10/31/remote-authentication-with-devise/" rel="nofollow" target="_blank"&gt;http://4trabes.com/2012/10/31/remote-authentication-with-devise/&lt;/a&gt;&lt;/p&gt;</description>
      <author>sanvi</author>
      <pubDate>Mon, 16 Sep 2013 11:18:11 +0800</pubDate>
      <link>https://ruby-china.org/topics/14151</link>
      <guid>https://ruby-china.org/topics/14151</guid>
    </item>
    <item>
      <title>怎么才能测试 grape 的 api</title>
      <description>&lt;p&gt;1) FileServer::API GET /api/apps/:app with apk real number code
     Failure/Error: get "/api/apps/s"
     NoMethodError:
       undefined method &lt;code&gt;call' for #&amp;lt;App:0x007f8ac2096830&amp;gt;
     # ./spec/api/api_spec.rb:11:in&lt;/code&gt;block (4 levels) in '&lt;/p&gt;

&lt;p&gt;我想在 rspec 里面去 测试 grape 的 api，但是他总是报这个错误&lt;/p&gt;

&lt;p&gt;我在浏览器里直接可以访问&lt;/p&gt;

&lt;p&gt;已经尝试增加&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include&lt;/span&gt; &lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;RequestExampleGroup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:type&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:example_group&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="ss"&gt;:file_path&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="sr"&gt;/spec\/api/&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;</description>
      <author>sanvi</author>
      <pubDate>Wed, 11 Sep 2013 16:43:08 +0800</pubDate>
      <link>https://ruby-china.org/topics/14041</link>
      <guid>https://ruby-china.org/topics/14041</guid>
    </item>
    <item>
      <title>有关 RSpec 的一些问题</title>
      <description>&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;#models/build.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Build&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Mongoid&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Document&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Mongoid&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Timestamps&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:attachment&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;#models/attachment.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Attachment&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Mongoid&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Document&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Mongoid&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Timestamps&lt;/span&gt;

  &lt;span class="n"&gt;mount_uploader&lt;/span&gt; &lt;span class="ss"&gt;:file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;AttachmentUploader&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;#spec/controllers/builds_controller_spec.rb&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'spec_helper'&lt;/span&gt;

&lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;BuildsController&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;


  &lt;span class="n"&gt;before&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:all&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="vi"&gt;@build&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;FactoryGirl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:build&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"has a valid factory"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;FactoryGirl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:app&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt; &lt;span class="n"&gt;be_valid&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s2"&gt;"POST 'create'"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;login_user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:attachment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:attachment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:build&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:build&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;attachment: &lt;/span&gt;&lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;'when upload apk'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'creates with apk'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
            &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="s1"&gt;'create'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:build&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;FactoryGirl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attributes_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:build&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;build_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;build&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;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;#factories/builds.rb&lt;/span&gt;
&lt;span class="c1"&gt;# Read about factories at https://github.com/thoughtbot/factory_girl&lt;/span&gt;

&lt;span class="no"&gt;FactoryGirl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;factory&lt;/span&gt; &lt;span class="ss"&gt;:build&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="c1"&gt;#fields&lt;/span&gt;
    &lt;span class="n"&gt;attachment&lt;/span&gt; 
    &lt;span class="c1"&gt;# { FactoryGirl.build(:attachment) }&lt;/span&gt;
    &lt;span class="n"&gt;note&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;Faker&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Lorem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&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;span class="c1"&gt;#factories/attachments.rb&lt;/span&gt;
&lt;span class="c1"&gt;# Read about factories at https://github.com/thoughtbot/factory_girl&lt;/span&gt;
&lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;ActionDispatch&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;TestProcess&lt;/span&gt;

&lt;span class="no"&gt;FactoryGirl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;factory&lt;/span&gt; &lt;span class="ss"&gt;:attachment&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  &lt;span class="no"&gt;Rack&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Test&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;UploadedFile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="sx"&gt;%w[spec factories data attachment calc-android-china.apk]&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;'application/vnd.android.package-archive'&lt;/span&gt;&lt;span class="p"&gt;)&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;代码如上，有一些问题&lt;/p&gt;

&lt;p&gt;首先&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;'when upload apk'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'creates with apk'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="s1"&gt;'create'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:build&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;FactoryGirl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attributes_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:build&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;build_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;build&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;其中
1.FactoryGirl.attributes_for(:build) 是不是会直接拿 FactoryGirl 里面构建的 build，那么我后面直接用 build 是否跟这个是同一个对象？
2.rspec 出现以下错误&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="no"&gt;BuildsController&lt;/span&gt; &lt;span class="no"&gt;POST&lt;/span&gt; &lt;span class="s1"&gt;'create'&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="n"&gt;upload&lt;/span&gt; &lt;span class="n"&gt;apk&lt;/span&gt; &lt;span class="n"&gt;creates&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;apk&lt;/span&gt;
   &lt;span class="no"&gt;Failure&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="no"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:attachment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:attachment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="no"&gt;NoMethodError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
     &lt;span class="n"&gt;undefined&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt; &lt;span class="sb"&gt;`create' for #&amp;lt;RSpec::Core::ExampleGroup::Nested_1::Nested_1::Nested_1:0x007fb5d3ddddb8&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;为什么呢？不是可以直接构建吗？
3.我 build 里面是关联 attachment，那么    let(:build) { create(:build, attachment: attachment) }，我在后面应该能拿到 build.attachment，那为何是 nil？&lt;/p&gt;

&lt;p&gt;暂时就这么多问题&lt;/p&gt;</description>
      <author>sanvi</author>
      <pubDate>Wed, 04 Sep 2013 11:51:31 +0800</pubDate>
      <link>https://ruby-china.org/topics/13879</link>
      <guid>https://ruby-china.org/topics/13879</guid>
    </item>
    <item>
      <title>最近做的一个移动客服的插件</title>
      <description>&lt;p&gt;这个是最近跟小伙伴跟折腾的项目&lt;/p&gt;

&lt;p&gt;一个基于即时通讯的客服 SDK
信 + 客服，正式发布【免费下载使用】&lt;/p&gt;

&lt;p&gt;&lt;a href="http://xin.io/" rel="nofollow" target="_blank" title="信+"&gt;http://xin.io/ &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;欢迎吐槽^_^&lt;/p&gt;

&lt;p&gt;联系 QQ：2841923364&lt;/p&gt;

&lt;p&gt;有图有真相
&lt;img src="//l.ruby-china.com/photo/62fcbb2274e25061430c2a18db78019b.png" title="" alt=""&gt;&lt;/p&gt;</description>
      <author>sanvi</author>
      <pubDate>Wed, 28 Aug 2013 14:01:02 +0800</pubDate>
      <link>https://ruby-china.org/topics/13693</link>
      <guid>https://ruby-china.org/topics/13693</guid>
    </item>
    <item>
      <title>最近老是看到 XX 网站给墙了。。</title>
      <description>&lt;p&gt;节约生命，善用梯子.....&lt;/p&gt;

&lt;p&gt;= = 好吧，我来引口水的~&lt;/p&gt;</description>
      <author>sanvi</author>
      <pubDate>Fri, 23 Aug 2013 15:33:30 +0800</pubDate>
      <link>https://ruby-china.org/topics/13550</link>
      <guid>https://ruby-china.org/topics/13550</guid>
    </item>
    <item>
      <title>NodeJS 的一些疑惑，我来跑题了</title>
      <description>&lt;p&gt;Nodejs 貌似启动就是单核单进程的&lt;/p&gt;

&lt;p&gt;那么我启动 node 后，需要用多核怎么办？&lt;/p&gt;

&lt;p&gt;我看外面好像是凯多个 instance，用 nginx 在实现绑定&lt;/p&gt;

&lt;p&gt;那么又有疑问了，他们是相对独立的吗？那么如何做数据共享呢？&lt;/p&gt;

&lt;p&gt;还有种方式是 fork 多个子进程（是子进程吗？），然后绑定到同一个端口上，那么他们的数据是如何共享的？&lt;/p&gt;

&lt;p&gt;假设我有 NodeA,NodeB,NodeC3 个进程都绑定在同一个端口 3000 上&lt;/p&gt;

&lt;p&gt;那么 NodeA 里面有个 Array，NodeB 和 NodeC 知道吗？&lt;/p&gt;

&lt;p&gt;那么如果客户端访问 3000，是访问有 NodeA,NodeB,NodeC3 其中哪一个&lt;/p&gt;</description>
      <author>sanvi</author>
      <pubDate>Mon, 22 Jul 2013 14:46:09 +0800</pubDate>
      <link>https://ruby-china.org/topics/12671</link>
      <guid>https://ruby-china.org/topics/12671</guid>
    </item>
    <item>
      <title>有没发现最近的跑步贴很火</title>
      <description>&lt;p&gt;建议开个版专门讨论健康的问题&lt;/p&gt;

&lt;p&gt;程序员的健康问题其实非常值得关注，大多数人都不关心的&lt;/p&gt;

&lt;p&gt;像跑步游泳这些应该让更多的人去尝试起来，改善身体&lt;/p&gt;

&lt;p&gt;11 年的时候就因为健康问题病倒了一次，后来是因为想减肥开始跑步&lt;/p&gt;

&lt;p&gt;各位动起来吧~~~^_^&lt;/p&gt;</description>
      <author>sanvi</author>
      <pubDate>Fri, 19 Jul 2013 09:21:00 +0800</pubDate>
      <link>https://ruby-china.org/topics/12600</link>
      <guid>https://ruby-china.org/topics/12600</guid>
    </item>
    <item>
      <title>很奇怪的一个 bug</title>
      <description>&lt;p&gt;我的账户会自动变成这个账户，并且可以使用他的账户做任何操作
  第 144 位会员
ID: linsk
Since: 2011 年 11 月 20 日&lt;/p&gt;

&lt;p&gt;本来以为退出重新登录就 OK 了，结果还是会变成这个账户&lt;/p&gt;</description>
      <author>sanvi</author>
      <pubDate>Thu, 18 Jul 2013 14:45:14 +0800</pubDate>
      <link>https://ruby-china.org/topics/12589</link>
      <guid>https://ruby-china.org/topics/12589</guid>
    </item>
    <item>
      <title>有没有办法去监控 nodejs</title>
      <description>&lt;p&gt;有没办法去监控 nodejs 进程&lt;/p&gt;

&lt;p&gt;挂了好歹发封邮件通知下我之类得。。。&lt;/p&gt;

&lt;p&gt;rails 相对稳定点，不会挂，所以不太担心&lt;/p&gt;</description>
      <author>sanvi</author>
      <pubDate>Tue, 02 Jul 2013 17:47:15 +0800</pubDate>
      <link>https://ruby-china.org/topics/12190</link>
      <guid>https://ruby-china.org/topics/12190</guid>
    </item>
    <item>
      <title>Rails 的值怎么传入 angularjs</title>
      <description>&lt;p&gt;比如我在 Controller.rb 里面有个
def test
  &lt;a href="/aa" class="user-mention" title="@aa"&gt;&lt;i&gt;@&lt;/i&gt;aa&lt;/a&gt; = ['xx','xx','xx']
end&lt;/p&gt;

&lt;p&gt;那么我在页面上
&amp;lt;%= &lt;a href="/aa" class="user-mention" title="@aa"&gt;&lt;i&gt;@&lt;/i&gt;aa&lt;/a&gt; %&amp;gt;&lt;/p&gt;

&lt;p&gt;那么我怎么传入到 angularjs 的 scope&lt;/p&gt;

&lt;p&gt;function AppCtrl($scope, socket){&lt;/p&gt;

&lt;p&gt;$scope.aa = []
}&lt;/p&gt;</description>
      <author>sanvi</author>
      <pubDate>Sat, 22 Jun 2013 11:04:24 +0800</pubDate>
      <link>https://ruby-china.org/topics/11900</link>
      <guid>https://ruby-china.org/topics/11900</guid>
    </item>
    <item>
      <title>关于性能测试的一些疑问</title>
      <description>&lt;p&gt;经常看到某单台服务器 XXXK 并发云云的，没玩过这么大型的东西，所以有些疑问&lt;/p&gt;

&lt;p&gt;1.并发数是不是连接数？
比如同时 100k 个人访问你的主页，那么就是 100k 个 request？
那么是不是就是说你 nginx 的性能？
怎么去测试？
用 AB 吗？或许有更好的方式？&lt;/p&gt;

&lt;p&gt;2.如果你里面涉及长连接，那么如何测试长连接呢
100K 个长连接，也是用 AB 来测试吗？（貌似我就只知道 AB）&lt;/p&gt;

&lt;p&gt;3.如何衡量你的性能
我用 AB 跑了下，发现 2000 也能跑，20000 也能跑，只是数值不太一样而已，那么说我也支持 20000 并发&lt;/p&gt;

&lt;p&gt;4.测试工具的运行
我是要把 AB 跑在我的电脑上还是在服务器上自己炸自己？&lt;/p&gt;

&lt;p&gt;各种坑爹的疑问，希望解答&lt;/p&gt;</description>
      <author>sanvi</author>
      <pubDate>Sat, 15 Jun 2013 10:58:48 +0800</pubDate>
      <link>https://ruby-china.org/topics/11737</link>
      <guid>https://ruby-china.org/topics/11737</guid>
    </item>
  </channel>
</rss>
