<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>308820773 (黑)</title>
    <link>https://ruby-china.org/308820773</link>
    <description></description>
    <language>en-us</language>
    <item>
      <title>(代码) 用 Rails 实现一个 sse  API</title>
      <description>&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StreamController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActionController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;API&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;ActionController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Live&lt;/span&gt;

  &lt;span class="n"&gt;before_action&lt;/span&gt; &lt;span class="k"&gt;do&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;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Content-Type'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;                 &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'text/event-stream'&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;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Last-Modified"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;                &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;httpdate&lt;/span&gt;   &lt;span class="c1"&gt;# TODO 3 &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;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Access-Control-Allow-Origin'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&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;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Access-Control-Allow-Methods'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'GET, POST, OPTIONS'&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;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Access-Control-Allow-Headers'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type, Authorization'&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;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Cache-Control'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;                &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'no-cache'&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;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Connection'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;                   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'keep-alive'&lt;/span&gt;

    &lt;span class="vi"&gt;@sse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;SSE&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="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# TODO 1 &lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;rescue_from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;RecordNotFound&lt;/span&gt;&lt;span class="p"&gt;)&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;e&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="vi"&gt;@sse.write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;status: &lt;/span&gt;&lt;span class="mi"&gt;404&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;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@sse.close&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# params&lt;/span&gt;
  &lt;span class="c1"&gt;# {&lt;/span&gt;
  &lt;span class="c1"&gt;#   chat_id: 1,&lt;/span&gt;
  &lt;span class="c1"&gt;#   content: 'Hello',&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;talk&lt;/span&gt;
    &lt;span class="no"&gt;Chats&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;GetAnswer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&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="vi"&gt;@sse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# ensure # TODO 2 &lt;/span&gt;
    &lt;span class="c1"&gt;#   @sse.close&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;TODO 1. SSE.new(response.stream, retry: 300), 返回 sse 数据时，会把 retry: 300 返回，这个是正常？&lt;/p&gt;

&lt;p&gt;TODO 2. ensure 这里不可以 close, 因为 rescue_from 的执行是在  ensure 之后的，有没有更优雅的写法&lt;/p&gt;

&lt;p&gt;TODO 3.  感谢 rennyallen 的 &lt;a href="https://ruby-china.org/topics/43052" rel="nofollow" target="_blank"&gt;https://ruby-china.org/topics/43052&lt;/a&gt; 这篇文章，rack &amp;gt;= 2.2x 需要加上这行&lt;/p&gt;

&lt;p&gt;TODO 4. 如果你用 nginx  proxy, 还需要再 conf 文件里加上
    proxy_set_header Connection '';
    proxy_http_version 1.1;
    chunked_transfer_encoding off;&lt;/p&gt;

&lt;p&gt;总结：sse 在 rails 里还是做不到开箱即用，有些细节和小坑要注意下&lt;/p&gt;</description>
      <author>308820773</author>
      <pubDate>Wed, 20 Aug 2025 14:53:14 +0800</pubDate>
      <link>https://ruby-china.org/topics/44249</link>
      <guid>https://ruby-china.org/topics/44249</guid>
    </item>
    <item>
      <title>付费咨询一个 canvas lms 创建 LTI 的问题</title>
      <description>&lt;p&gt;有意+v 联系，SuperGoldberg&lt;/p&gt;</description>
      <author>308820773</author>
      <pubDate>Wed, 15 Jan 2025 17:55:22 +0800</pubDate>
      <link>https://ruby-china.org/topics/44020</link>
      <guid>https://ruby-china.org/topics/44020</guid>
    </item>
    <item>
      <title>2024 年了，这样的极简 API 你喜欢么</title>
      <description>&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/308820773/ac4a3fd8-6dc8-4390-a568-07f7fd999d54.png!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;项目基于 Rails 7 和 grape, 集成权限管理 rolify, 可以控制路由权限，也可以控制资源权限  &lt;/p&gt;

&lt;p&gt;项目地址：&lt;a href="https://github.com/blackerhand/rails-api-grape" rel="nofollow" target="_blank"&gt;https://github.com/blackerhand/rails-api-grape&lt;/a&gt;&lt;/p&gt;</description>
      <author>308820773</author>
      <pubDate>Fri, 12 Jan 2024 10:44:09 +0800</pubDate>
      <link>https://ruby-china.org/topics/43544</link>
      <guid>https://ruby-china.org/topics/43544</guid>
    </item>
    <item>
      <title>写了个 graphql-ruby 的实现, 可以当入门使用</title>
      <description>&lt;p&gt;最近在研究 graphql, 看来下官方 gem, 感觉目录分层和 i18n 处理的太基础了，没有给太多的实现方案，所以自己整理了下，加入了目录分层，i18n&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/308820773/rails-api-graphql" rel="nofollow" target="_blank"&gt;https://github.com/308820773/rails-api-graphql&lt;/a&gt;&lt;/p&gt;</description>
      <author>308820773</author>
      <pubDate>Fri, 18 Sep 2020 11:54:29 +0800</pubDate>
      <link>https://ruby-china.org/topics/40419</link>
      <guid>https://ruby-china.org/topics/40419</guid>
    </item>
    <item>
      <title>没人感觉  graphql.cn 的文档写的太垃圾么?</title>
      <description>&lt;p&gt;最近在看 graphql, 就从 graphql.cn 的文档开始看。越看越发现，这个文档写的太垃圾，作者善于把简单的问题复杂化。&lt;/p&gt;</description>
      <author>308820773</author>
      <pubDate>Mon, 09 Sep 2019 11:12:44 +0800</pubDate>
      <link>https://ruby-china.org/topics/39026</link>
      <guid>https://ruby-china.org/topics/39026</guid>
    </item>
    <item>
      <title>基于 Rails+Garpe 开发前后端分离网站 - 后端</title>
      <description>&lt;h2 id="相关技术"&gt;相关技术&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;rails 5.2.3&lt;/li&gt;
&lt;li&gt;grape 1.2&lt;/li&gt;
&lt;li&gt;grape entity 0.7&lt;/li&gt;
&lt;li&gt;swagger &lt;/li&gt;
&lt;li&gt;kaminari&lt;/li&gt;
&lt;li&gt;jwt + bcrypt&lt;/li&gt;
&lt;li&gt;mysql2 &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/308820773/rails-api-grape" rel="nofollow" target="_blank"&gt;https://github.com/308820773/rails-api-grape&lt;/a&gt;&lt;/p&gt;</description>
      <author>308820773</author>
      <pubDate>Sun, 12 May 2019 18:38:26 +0800</pubDate>
      <link>https://ruby-china.org/topics/38514</link>
      <guid>https://ruby-china.org/topics/38514</guid>
    </item>
    <item>
      <title>Rails 如何利用 Stomp 订阅 Apache ActiveMQ 的 Message</title>
      <description>&lt;p&gt;背景：公司有套 java 系统，里面用的是 ActiveMQ 来做消息通知。现用 rails  开发了另外一 web 服务。然后 rails 里有个小功能是现在的 java 系统要使用的，就想着用 ActiveMQ 来进行信息的交互。&lt;/p&gt;

&lt;p&gt;实现方式：首先 java 系统给 ActiveMQ 的 '/queus/java-rails' 发送一条消息，rails 利用 stomp 来 subscribe  '/queus/java-rails' 的消息，执行相关代码之后，把结果发送给 ActiveMQ '/queus/rails-java'. &lt;/p&gt;

&lt;p&gt;目前代码&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;MyStomp&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;
    &lt;span class="vi"&gt;@username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'admin'&lt;/span&gt;
    &lt;span class="vi"&gt;@password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'admin'&lt;/span&gt;
    &lt;span class="vi"&gt;@hostname&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'localhost'&lt;/span&gt;
    &lt;span class="vi"&gt;@port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'61613'&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;run&lt;/span&gt;
    &lt;span class="vi"&gt;@client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Stomp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Client&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="vi"&gt;@username&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="vi"&gt;@hostname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="vi"&gt;@client.subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"'/queus/java-rails"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;id: &lt;/span&gt;&lt;span class="vi"&gt;@client.uuid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'ack'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'auto'&lt;/span&gt;&lt;span class="p"&gt;)&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;msg&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="vi"&gt;@client.publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/queue/rails-java"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"任务执行完了"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Connected"&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;shutdown&lt;/span&gt;
    &lt;span class="vi"&gt;@client.close&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@client&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s1"&gt;'DisConnected'&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;# 启动订阅&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;MyStomp&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;begin&lt;/span&gt;
  &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;
&lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;SystemExit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Interrupt&lt;/span&gt;
  &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shutdown&lt;/span&gt;
&lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
  &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shutdown&lt;/span&gt;
  &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;问题：该怎么在 rails 内组织代码呢，以及该如何启动该订阅？&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;封装 为一个 bin 命令，rails 启动后，再执行该命令 &lt;/li&gt;
&lt;li&gt;执行一个 rake 任务？试了下好像不行&lt;/li&gt;
&lt;/ul&gt;</description>
      <author>308820773</author>
      <pubDate>Thu, 21 Mar 2019 15:56:58 +0800</pubDate>
      <link>https://ruby-china.org/topics/38269</link>
      <guid>https://ruby-china.org/topics/38269</guid>
    </item>
    <item>
      <title>分析 Ruby 中的比较函数</title>
      <description>&lt;p&gt;在学习 spec 的时候，有个 eq 匹配器不是很理解，所以查了下资料.
发现 ruby 中的比较函数，&lt;code&gt;eql?&lt;/code&gt; &lt;code&gt;equal?&lt;/code&gt; &lt;code&gt;==&lt;/code&gt; &lt;code&gt;===&lt;/code&gt; &lt;code&gt;is_a?&lt;/code&gt; &lt;code&gt;kind_of?&lt;/code&gt; &lt;code&gt;instance_of?&lt;/code&gt; 傻傻分不清楚。
还有&lt;code&gt;nil?&lt;/code&gt; &lt;code&gt;empty?&lt;/code&gt; &lt;code&gt;blank?&lt;/code&gt; &lt;code&gt;present?&lt;/code&gt; 几个函数。也是比较容易引起混淆。&lt;/p&gt;

&lt;p&gt;抽时间整理了下，如果有错误，欢迎指正。&lt;/p&gt;

&lt;hr&gt;
&lt;h2 id="eql?"&gt;eql?&lt;/h2&gt;
&lt;p&gt;一般情况下，表现与 &lt;code&gt;==&lt;/code&gt; 相同。hash 里面 key 的比较，就是采用的这个函数。比如 {1.0 =&amp;gt; 'a', 1 =&amp;gt;'b'}, 代表两个不同 key 值。&lt;/p&gt;
&lt;h2 id="equal?"&gt;equal?&lt;/h2&gt;
&lt;p&gt;用来判定，内存地址相同的对象，使用的时候，不应覆盖此方法。有点类似于 JavaScript 中的 ===. 这里稍微引申下。a = 'b', b = 'b', a.equal?(b) 是返回 false 的，因为定义变量 a, b 的时候，生成了两个字符串变量 'b'. 他们的 object_id 是不一样的。而如果 a = 'b', b = a, 此时相比则返回的是 true. &lt;/p&gt;
&lt;h2 id="=="&gt;==&lt;/h2&gt;
&lt;p&gt;一般意义的值比较。可以跨类使用。比如 Float 和 Fixnum 类之间的比较。
1.0 == 1 结果是 true 的。就是因为覆盖了相应的 == 方法。&lt;/p&gt;
&lt;h2 id="==="&gt;===&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;case&lt;/code&gt; 里会调用该方法。假设 b = A.new , 调用 A === b, 当 a 为 Class 对象的时候，会调用 b.kind_of? a, 结果是返回 true 的，但是 b === a, 则会返回 false. 同理，当你 case b when A, 此时 when 里面的代码块也会执行，其他情况下，表现与 == 相同。&lt;/p&gt;
&lt;h2 id="is_a?/kind_of?"&gt;is_a?/kind_of?&lt;/h2&gt;
&lt;p&gt;检查 一个对象是否是 Class 的一个实例。Class 可以不是 对象类的父类。&lt;/p&gt;
&lt;h2 id="instance_of"&gt;instance_of&lt;/h2&gt;
&lt;p&gt;检查 一个对象是否是 Class 的一个实例。Class 不可以是 对象类的父类。比如 a.instance_of B 可以翻译为 a.class == B&lt;/p&gt;

&lt;p&gt;具体如下&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;   &lt;span class="c1"&gt;# true&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;    &lt;span class="c1"&gt;# true&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eql?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# false&lt;/span&gt;

&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s1"&gt;'string'&lt;/span&gt;
&lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;
  &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="s1"&gt;'ok'&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="c1"&gt;# ok&lt;/span&gt;

&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt; 
&lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'string'&lt;/span&gt;
  &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="s1"&gt;'ok'&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
  &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="c1"&gt;# false &lt;/span&gt;

&lt;span class="no"&gt;String&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s1"&gt;'string'&lt;/span&gt; &lt;span class="c1"&gt;# true &lt;/span&gt;
&lt;span class="s1"&gt;'string'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;kind_of?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# true&lt;/span&gt;
&lt;span class="s1"&gt;'string'&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt; &lt;span class="c1"&gt;# false &lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;class&lt;/span&gt; &lt;span class="c1"&gt;# Fixnum&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;kind_of?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# true&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instance_of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;================ 扩展============&lt;/p&gt;
&lt;h2 id="nil?"&gt;nil?&lt;/h2&gt;
&lt;p&gt;只有 nil 的时候会返回 true.&lt;/p&gt;
&lt;h2 id="empty?"&gt;empty?&lt;/h2&gt;
&lt;p&gt;nil 调用会报错，检查一个对象为空。字符串，数组，hash 会检查 length 是否等于 0. &lt;/p&gt;
&lt;h2 id="blank?"&gt;blank?&lt;/h2&gt;
&lt;p&gt;rails 的方法，相当于 &lt;code&gt;nil? || empty?&lt;/code&gt;(这是错误的) 
.blank? 还会在前者的基础上检查 字符串是否为空白，空格，tab, 换行 都是空白。
ruby 中，单引号定义的 字符串不会转义，双引号定义的字符串会转义。
所以 '\n'.blank? 为 false, "\n".blank? 为 true&lt;/p&gt;
&lt;h2 id="present?"&gt;present?&lt;/h2&gt;
&lt;p&gt;rails 的方法，相当于 !blank?&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt; &lt;span class="c1"&gt;# if 时为 false&lt;/span&gt;

&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;
&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt;

&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt; &lt;span class="c1"&gt;# if 时为 false&lt;/span&gt;
&lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;

&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;temp: &lt;/span&gt;&lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;

&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt; &lt;span class="c1"&gt;# true&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt; &lt;span class="c1"&gt;# false&lt;/span&gt;
&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt; &lt;span class="c1"&gt;# false&lt;/span&gt;
&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt; &lt;span class="c1"&gt;# false&lt;/span&gt;
&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt; &lt;span class="c1"&gt;# false &lt;/span&gt;
&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt; &lt;span class="c1"&gt;# false &lt;/span&gt;
&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt; &lt;span class="c1"&gt;# false &lt;/span&gt;
&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt; &lt;span class="c1"&gt;# false &lt;/span&gt;
&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt; &lt;span class="c1"&gt;# false &lt;/span&gt;
&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt; &lt;span class="c1"&gt;# false &lt;/span&gt;
&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt; &lt;span class="c1"&gt;# false &lt;/span&gt;

&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt; &lt;span class="c1"&gt;# undefined method&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt; &lt;span class="c1"&gt;# true&lt;/span&gt;
&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt; &lt;span class="c1"&gt;# false&lt;/span&gt;
&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt; &lt;span class="c1"&gt;# true&lt;/span&gt;
&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt; &lt;span class="c1"&gt;# true&lt;/span&gt;
&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt; &lt;span class="c1"&gt;# undefined method&lt;/span&gt;
&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt; &lt;span class="c1"&gt;# undefined method&lt;/span&gt;
&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt; &lt;span class="c1"&gt;# false &lt;/span&gt;
&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt; &lt;span class="c1"&gt;# false &lt;/span&gt;
&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt; &lt;span class="c1"&gt;# undefined method &lt;/span&gt;
&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt; &lt;span class="c1"&gt;# undefined method&lt;/span&gt;

&lt;span class="c1"&gt;# only used in rails &lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blank?&lt;/span&gt; &lt;span class="c1"&gt;# true&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blank?&lt;/span&gt; &lt;span class="c1"&gt;# true&lt;/span&gt;
&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blank?&lt;/span&gt; &lt;span class="c1"&gt;# true&lt;/span&gt;
&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blank?&lt;/span&gt; &lt;span class="c1"&gt;# true&lt;/span&gt;
&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blank?&lt;/span&gt; &lt;span class="c1"&gt;# true&lt;/span&gt;
&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blank?&lt;/span&gt; &lt;span class="c1"&gt;# true &lt;/span&gt;
&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blank?&lt;/span&gt; &lt;span class="c1"&gt;# false &lt;/span&gt;
&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blank?&lt;/span&gt; &lt;span class="c1"&gt;# false &lt;/span&gt;
&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blank?&lt;/span&gt; &lt;span class="c1"&gt;# false &lt;/span&gt;
&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blank?&lt;/span&gt; &lt;span class="c1"&gt;# false &lt;/span&gt;
&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blank?&lt;/span&gt; &lt;span class="c1"&gt;# false &lt;/span&gt;

&lt;span class="c1"&gt;# only used in rails &lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;present?&lt;/span&gt; &lt;span class="c1"&gt;# false&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;present?&lt;/span&gt; &lt;span class="c1"&gt;# false&lt;/span&gt;
&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;present?&lt;/span&gt; &lt;span class="c1"&gt;# false&lt;/span&gt;
&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;present?&lt;/span&gt; &lt;span class="c1"&gt;# false&lt;/span&gt;
&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;present?&lt;/span&gt; &lt;span class="c1"&gt;# false&lt;/span&gt;
&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;present?&lt;/span&gt; &lt;span class="c1"&gt;# false &lt;/span&gt;
&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;present?&lt;/span&gt; &lt;span class="c1"&gt;# true &lt;/span&gt;
&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;present?&lt;/span&gt; &lt;span class="c1"&gt;# true &lt;/span&gt;
&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;present?&lt;/span&gt; &lt;span class="c1"&gt;# true &lt;/span&gt;
&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;present?&lt;/span&gt; &lt;span class="c1"&gt;# true &lt;/span&gt;
&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;present?&lt;/span&gt; &lt;span class="c1"&gt;# true &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;</description>
      <author>308820773</author>
      <pubDate>Fri, 30 Dec 2016 15:44:06 +0800</pubDate>
      <link>https://ruby-china.org/topics/32026</link>
      <guid>https://ruby-china.org/topics/32026</guid>
    </item>
  </channel>
</rss>
