<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>monsterooo (monsterooo)</title>
    <link>https://ruby-china.org/monsterooo</link>
    <description></description>
    <language>en-us</language>
    <item>
      <title>[成都] 拟合未来科技 (Fiture) 招聘前端工程师 (14-24K·14 薪)</title>
      <description>&lt;p&gt;作为未来科技健身方式的开创者和引领者，FITURE（成都拟合未来科技有限公司）致力于通过科技帮助大众建立健康的生活方式。在成立之初 FITURE 就已获得红杉资本的投资，目前也已完成 A 轮 6500 万美金融资，腾讯领投，C 资本，凯辉基金，黑蚁资本，CPE（中信产业基金），BAI（贝塔斯曼亚洲投资基金），全明星基金跟投。FITURE 的天使轮股东红杉资本中国基金在本轮中也继续追加投资。&lt;/p&gt;

&lt;p&gt;通过技术创新，FITURE 为用户提供了集科技健身硬件、虚拟教练专业指导、海量顶级健身课程、专业健身社区服务在内的科技健身方式服务。&lt;/p&gt;

&lt;p&gt;立足于科技健身方式领域的同时，FITURE 还利用自身的技术优势和数据积累，探索基于用户的运动数据及生理数据提供诸如饮食建 议、健康管理等其它生活服务，布局全面的智能健康管理领域，为大众打造属于每个人的健康生活方式！&lt;/p&gt;

&lt;p&gt;FITURE 创始团队具有极强的科技与互联网行业背景，包括满帮集团、智加科技、腾讯、亚马逊等公司的前高管。核心团队均有优秀研发背景，毕业于哈佛、卡耐基梅隆、清华大学、上海交大等顶尖院校，集合了自动驾驶、机器人、互联网等各科技领域的世界级人才。&lt;/p&gt;
&lt;h2 id="产品介绍"&gt;产品介绍&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.fiture.com" rel="nofollow" target="_blank" title=""&gt;FITURE Power / Slim&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;FITURE 力求通过科技帮助大众建立健康的生活方式。通过技术创新，FITURE 为用户提供了集智能硬件、AI 教练、丰富课程、专业服务在内的科技健身方式。同时，FITURE 还利用技术优势和数据积累，为用户提供饮食建议、健康管理等其它生活服务，布局全面的智能健康管理领域，为大众打造属于每个人的健康生活方式！&lt;/p&gt;
&lt;h2 id="工作时间"&gt;工作时间&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;早上 10 点到下午 6.30&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="职位描述"&gt;职位描述&lt;/h2&gt;
&lt;p&gt;中 - 高级前端工程师&lt;/p&gt;
&lt;h2 id="工作情况简介"&gt;工作情况简介&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;公司有良好的企业文化 &amp;amp; 职业上升通道&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;完善的代码规范 &amp;amp; 前端基础设施&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="职位要求"&gt;职位要求&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;3 年以上 Web 开发相关经验&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;熟练使用 React 进行前端页面开发&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;能够快速完成复杂中后台页面的开发 or 还原度极高的前台页面开发&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;有良好的代码规范意识，熟悉并遵从常见的 Lint 规则&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;基本功扎实，有良好的代码设计能力，能够写出可读性好的代码&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;良好的英语水平，能够轻松读懂开发中常见英文文档、各种常见错误提示&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;良好的沟通能力，团队协作意识，有责任心，能抗压力&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="加分项"&gt;加分项&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;系统性的学习过前端开发相关书籍，如红宝书、绿皮书、重构等等&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;有个人博客，且博客中有较高质量的内容&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;有开源项目，能够展示出较好的代码习惯&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="待遇"&gt;待遇&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;MacBook Pro + Dell 显示器；&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;月薪 14-24K · 14 薪;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;完整社保、公积金、以及带薪年假；&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;内部组织的各种兴趣活动小组&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="工作地点"&gt;工作地点&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://surl.amap.com/HrfGG01hdII" rel="nofollow" target="_blank" title=""&gt;成都&lt;/a&gt; 天府软件园 E 区 E3-1 栋 9 楼&lt;/p&gt;
&lt;h2 id="简历投递"&gt;简历投递&lt;/h2&gt;
&lt;p&gt;简历 PDF 到：jiangzhu@fiture.com&lt;/p&gt;</description>
      <author>monsterooo</author>
      <pubDate>Mon, 08 Mar 2021 17:42:41 +0800</pubDate>
      <link>https://ruby-china.org/topics/41006</link>
      <guid>https://ruby-china.org/topics/41006</guid>
    </item>
    <item>
      <title>一个基于浏览器的编程工具 (Coderlane)</title>
      <description>&lt;h2 id="简单介绍"&gt;简单介绍&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://coderlane.net" rel="nofollow" target="_blank" title=""&gt;Coderlane&lt;/a&gt;是一款在线编程工具，您可以在浏览器中通过简单的点击 5 秒内创建一个编程语言环境。&lt;/p&gt;
&lt;h2 id="项目初心"&gt;项目初心&lt;/h2&gt;
&lt;p&gt;缘起于一个朋友的在线面试体验。面试官给他发了一个牛客网的链接，面试题目很简单：字符串去重并且在对应字符后面跟一个字符重复的数量。给定的时间是 30 分钟，但是我的朋友整整花了 15 分钟才研究明白他们的工具怎么使用。&lt;/p&gt;

&lt;p&gt;最终虽然他完成了面试题目，但是由于时间紧迫算法做的不算优化。最终导致没有得到二面的机会。&lt;/p&gt;

&lt;p&gt;所以我就开始构思做一个更好用的在线编程工具，使用起来无障碍且足够简单。&lt;/p&gt;
&lt;h2 id="第一版(3月)"&gt;第一版 (3 月)&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2019/40c080ad-a195-49a5-95c9-cb77e9935161.jpg!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;3 月份第一版出来了实现了最最基础的代码执行功能和跑测试用例。原理就是服务器跑一个 docker 去执行客户端的代码，拿到结果后返回给客户端&lt;/p&gt;

&lt;p&gt;虽然基础的功能出来了但是还是有许多不满足的地方，第一个就是界面不够简洁。&lt;/p&gt;
&lt;h2 id="第二版(6月)"&gt;第二版 (6 月)&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2019/698b45b2-9894-435f-a395-9db4eb4a6431.jpg!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;针对第一版的界面做了新的调整，界面更加美观并且我去掉了测试用例功能。&lt;/p&gt;

&lt;p&gt;第二版虽完成了，但是我并不太满足。主要原因有如下：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;代码同步太 low 没有考虑冲突解决方案&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;动态语言没有实现和客户端的 REPl 连接，只能返回结果&lt;/li&gt;
&lt;li&gt;没有音视频沟通功能&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="第三版(9月)"&gt;第三版 (9 月)&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2019/0e93fa7f-042b-43f0-94e2-a546c2371ad9.jpg!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;针对第二版的问题，我进行了功能的完善。解决方案如下：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;使用 Operational Transformation 算法解决多客户端编辑冲突问题&lt;/li&gt;
&lt;li&gt;使用伪终端代理打通 REPL，这样客户端可实时调试&lt;/li&gt;
&lt;li&gt;增加音视频服务功能这个要感谢 Agora 提供的服务&lt;/li&gt;
&lt;li&gt;增加编辑器的代码提示、自动补全、显示文档&lt;/li&gt;
&lt;li&gt;增加在编辑时实时显示用户正在编辑的位置&lt;/li&gt;
&lt;li&gt;增加了代码回放&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;我非常希望看到&lt;a href="https://coderlane.net" rel="nofollow" target="_blank" title=""&gt;Coderlane&lt;/a&gt;作为一个在线编程工具给大家带来更便捷的体验，并且我打算永久免费，直到无法负担运营成本为止。&lt;/p&gt;

&lt;p&gt;最后说一下我的感受：做一个项目不容易，做好更是需要付出很多努力和工作。希望大家多多提意见我们共同来完善&lt;a href="https://coderlane.net" rel="nofollow" target="_blank" title=""&gt;Coderlane&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;感谢阅读和使用&lt;/p&gt;</description>
      <author>monsterooo</author>
      <pubDate>Wed, 13 Nov 2019 15:57:57 +0800</pubDate>
      <link>https://ruby-china.org/topics/39247</link>
      <guid>https://ruby-china.org/topics/39247</guid>
    </item>
    <item>
      <title>Devise Pundit Rolify 学习笔记</title>
      <description>&lt;h4 id="1. 安装bundle和初始化"&gt;1. 安装 bundle 和初始化&lt;/h4&gt;
&lt;p&gt;1.1 devise 初始化&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bundle add devise &lt;span class="c"&gt;# 安装并添加到Gem&lt;/span&gt;
rails generate devise:install &lt;span class="c"&gt;# 运行生成器&lt;/span&gt;
rails generate devise User &lt;span class="c"&gt;# 创建模型&lt;/span&gt;
rails db:migrate &lt;span class="c"&gt;# 运行迁移任务&lt;/span&gt;

&lt;span class="c"&gt;# 验证以上步骤是否成功&lt;/span&gt;
rails s
&lt;span class="c"&gt;# 浏览器访问： http://localhost:3000/users/sign_in 看到登录画面就成功了&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;1.2 pundit 初始化&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bundle add pundit &lt;span class="c"&gt;# 安装并添加到Gem&lt;/span&gt;
rails g pundit:install &lt;span class="c"&gt;# 运行生成器&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;1.3 rolify 初始化&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bundle add rolify &lt;span class="c"&gt;# 安装并添加到Gem&lt;/span&gt;
rails g rolify Role User &lt;span class="c"&gt;# 添加Role和User模型&lt;/span&gt;
rails db:migrate &lt;span class="c"&gt;# 运行迁移任务&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;1.4 添加一个 Book 资源用于测试&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails g scaffold Book title:string description:text
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="2 Rolify 库学习"&gt;2 Rolify 库学习&lt;/h4&gt;
&lt;p&gt;按照&lt;a href="https://github.com/RolifyCommunity/rolify#4-add-a-role-to-a-user" rel="nofollow" target="_blank" title=""&gt;官方文档&lt;/a&gt;我们现在可以给一个 User 添加一个角色，在 shell 执行&lt;code&gt;rails c&lt;/code&gt;进入 rails 调试模式&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;u&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;first&lt;/span&gt; &lt;span class="c1"&gt;# 获取第一个用户&lt;/span&gt;
&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_role&lt;/span&gt; &lt;span class="ss"&gt;:admin&lt;/span&gt; &lt;span class="c1"&gt;# 给这个用户添加一个admin角色&lt;/span&gt;
&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;roles&lt;/span&gt; &lt;span class="c1"&gt;# 可以打印出当前已经存在的角色&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;下面是根据&lt;a href="https://github.com/RolifyCommunity/rolify/wiki/Usage" rel="nofollow" target="_blank" title=""&gt;官方文档&lt;/a&gt;的一些用法：&lt;/p&gt;
&lt;h4 id="2.1 给user添加role"&gt;2.1 给 user 添加 role&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;定义全局 role:&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;注：resource_type、resource_id 这里是为空表示全局&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;user&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;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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="nf"&gt;add_role&lt;/span&gt; &lt;span class="ss"&gt;:admin&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;roles 表数据&lt;/p&gt;
&lt;table class="table table-bordered table-striped"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th&gt;id&lt;/th&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;th&gt;resource_type&lt;/th&gt;
&lt;th&gt;resource_id&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;admin&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;定义 role 作用域给一个资源的实例&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;注：按照&lt;a href="https://github.com/RolifyCommunity/rolify#32-configure-your-resource-models" rel="nofollow" target="_blank" title=""&gt;操作指南&lt;/a&gt;，Book 类中需要调用&lt;code&gt;resourcify&lt;/code&gt;方可为 Book 资源提供&lt;code&gt;role&lt;/code&gt;的查询&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 针对Book.first这个实例(id)增加一个对应角色&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;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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="nf"&gt;add_role&lt;/span&gt; &lt;span class="ss"&gt;:moderator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;roles 表数据&lt;/p&gt;
&lt;table class="table table-bordered table-striped"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th&gt;id&lt;/th&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;th&gt;resource_type&lt;/th&gt;
&lt;th&gt;resource_id&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;moderator&lt;/td&gt;
&lt;td&gt;Book&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;定义 role 作用域给一个资源类&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;user&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;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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="nf"&gt;add_role&lt;/span&gt; &lt;span class="ss"&gt;:moderator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Forum&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;roles 表数据&lt;/p&gt;
&lt;table class="table table-bordered table-striped"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th&gt;id&lt;/th&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;th&gt;resource_type&lt;/th&gt;
&lt;th&gt;resource_id&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;moderator&lt;/td&gt;
&lt;td&gt;Book&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;h4 id="2.2 Role查询"&gt;2.2 Role 查询&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;检查 user 是否有全局 role&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;user&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;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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="nf"&gt;add_role&lt;/span&gt; &lt;span class="ss"&gt;:admin&lt;/span&gt; &lt;span class="c1"&gt;# 设置一个全局role&lt;/span&gt;
&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has_role?&lt;/span&gt; &lt;span class="ss"&gt;:admin&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;检查 user 是否具有给定的某一个全局 role&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;user&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;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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="nf"&gt;add_role&lt;/span&gt; &lt;span class="ss"&gt;:admin&lt;/span&gt;
&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_role&lt;/span&gt; &lt;span class="ss"&gt;:moderator&lt;/span&gt;
&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_role&lt;/span&gt; &lt;span class="ss"&gt;:client&lt;/span&gt;

&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has_any_role?&lt;/span&gt; &lt;span class="ss"&gt;:admin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:moderator&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;检查 user 是否拥有指定资源的 role&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;user&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;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&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="nf"&gt;add_role&lt;/span&gt; &lt;span class="ss"&gt;:moderator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Forum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt; &lt;span class="c1"&gt;# 设置一个role作用域给一个资源(id)&lt;/span&gt;
&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has_role?&lt;/span&gt; &lt;span class="ss"&gt;:moderator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Forum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has_role?&lt;/span&gt; &lt;span class="ss"&gt;:moderator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Forum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;last&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has_role?&lt;/span&gt; &lt;span class="ss"&gt;:moderator&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt; &lt;span class="c1"&gt;# 返回false是因为moderator是给某个资源的role权限, 不是全局的&lt;/span&gt;
&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has_role?&lt;/span&gt; &lt;span class="ss"&gt;:moderator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:any&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt; &lt;span class="c1"&gt;# 返回true，因为用户至少有一个moderator role&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;检查 user 是否拥有指定类的 role&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;user&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;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&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="nf"&gt;add_role&lt;/span&gt; &lt;span class="ss"&gt;:moderator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Forum&lt;/span&gt; &lt;span class="c1"&gt;# 设置一个role作用域为Forum类&lt;/span&gt;
&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has_role?&lt;/span&gt; &lt;span class="ss"&gt;:moderator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Forum&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has_role?&lt;/span&gt; &lt;span class="ss"&gt;:moderator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Forum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has_role?&lt;/span&gt; &lt;span class="ss"&gt;:moderator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Forum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;last&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has_role?&lt;/span&gt; &lt;span class="ss"&gt;:moderator&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has_role?&lt;/span&gt; &lt;span class="ss"&gt;:moderator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:any&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果想要查看更多关于 rolify 的资料请查看官方文档&lt;/p&gt;
&lt;h4 id="3 Pundit 学习"&gt;3 Pundit 学习&lt;/h4&gt;
&lt;p&gt;首先在你的类中&lt;code&gt;include Pundit&lt;/code&gt;，这一般是在&lt;code&gt;ApplicationController&lt;/code&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;ApplicationController&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;Base&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Pundit&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="3.1 Policies(策略)"&gt;3.1 Policies(策略)&lt;/h4&gt;
&lt;p&gt;Pundit 核心聚焦于 policy 类，我们需要将这些类放在&lt;code&gt;app/policies&lt;/code&gt;文件夹中。下面是一个简单的 policy 类展示了。它的作用是：如果是管理员或者帖子在未发布状态可以进行更新操作&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;PostPolicy&lt;/span&gt;
  &lt;span class="nb"&gt;attr_reader&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;:post&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;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
    &lt;span class="vi"&gt;@post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;post&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;update?&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;admin?&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;published?&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;所有的 Policy 类都是 Ruby 的纯对象，它会做如下几点假设：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;它的类名和模型名是相同的名称，只是后缀带有&lt;code&gt;Policy&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;第一个参数是&lt;code&gt;user&lt;/code&gt;，在我们的控制器中 Pundit 将调用&lt;code&gt;current_user&lt;/code&gt;方法来检索要发送给此参数的内容&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;第二个参数是某种&lt;code&gt;model&lt;/code&gt;对象，你将会检查&lt;code&gt;user&lt;/code&gt;对它是否有权限。这个对象不一定是&lt;code&gt;ActiveRecord&lt;/code&gt;或&lt;code&gt;ActiveModel&lt;/code&gt;，它可以是任何东西&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;policy 的类实现了一些查询方法，在什么情况下&lt;code&gt;update?&lt;/code&gt;、&lt;code&gt;create&lt;/code&gt;。一般来说映射到控制器的动作&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;下面是一个基本的使用示例：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/policies/post_policy.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PostPolicy&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationPolicy&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update?&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;admin?&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="ow"&gt;not&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;published?&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;code&gt;policy&lt;/code&gt;都会继承&lt;code&gt;ApplicationPolicy&lt;/code&gt;的默认策略&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/controllers/post_controller.rb&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;
  &lt;span class="vi"&gt;@post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&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="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="n"&gt;authorize&lt;/span&gt; &lt;span class="vi"&gt;@post&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@post.update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="vi"&gt;@post&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:edit&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;code&gt;authorize&lt;/code&gt;方法会自动推断实现了&lt;code&gt;PostPolicy&lt;/code&gt;的类，然后使用&lt;code&gt;current_user&lt;/code&gt;和给定的&lt;code&gt;@post&lt;/code&gt;记录。然后动过动作推荐出应该调用那个 Policy 方法。&lt;code&gt;authorize&lt;/code&gt;大概会做如下的事情：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="no"&gt;PostPolicy&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;current_user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@post&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;update?&lt;/span&gt;
  &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;Pundit&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;NotAuthorizedError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"not allowed to update? this &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vi"&gt;@post.inspect&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;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果路由动作名称和 policy 不匹配，可以通过给&lt;code&gt;authorize&lt;/code&gt;传递第二个参数来指定验证的方法&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;publish&lt;/span&gt;
&lt;span class="vi"&gt;@post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&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="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;authorize&lt;/span&gt; &lt;span class="vi"&gt;@post&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:update?&lt;/span&gt; &lt;span class="c1"&gt;# publish的校验使用policy中的update方法&lt;/span&gt;
&lt;span class="vi"&gt;@post.publish&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="vi"&gt;@post&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果你没有一个实例来给&lt;code&gt;authorize&lt;/code&gt;进行授权，你可以传递一个&lt;code&gt;Class&lt;/code&gt;如下所示&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Policy 文件&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PostPolicy&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationPolicy&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;admin_list?&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;admin?&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;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Controller&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;admin_list&lt;/span&gt;
  &lt;span class="n"&gt;authorize&lt;/span&gt; &lt;span class="no"&gt;Post&lt;/span&gt; &lt;span class="c1"&gt;# 我们没有特定的Post给authorize验证&lt;/span&gt;
  &lt;span class="c1"&gt;# 验证后的其他操作&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;authorize&lt;/code&gt;方法返回传递给他的第一个对象，所以你可以向下面这样链式书写&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;
  &lt;span class="vi"&gt;@user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;authorize&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;find&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="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;通过&lt;code&gt;policy&lt;/code&gt;你可以在视图中也可以校验权限，这对于 ui 逻辑的显示特别有用&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;% if policy(@post).update? %&amp;gt;
  &amp;lt;%= link_to "Edit post", edit_post_path(@post) %&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="3.2 Scopes"&gt;3.2 Scopes&lt;/h4&gt;
&lt;p&gt;如果你需要一个只有特定用户才能访问的视图列表数据，可以使用 Pundit 的 Scope 比如下面这样&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;PostPolicy&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationPolicy&lt;/span&gt;
  &lt;span class="c1"&gt;# 其他的正常Policy&lt;/span&gt;

  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Scope&lt;/span&gt;
    &lt;span class="nb"&gt;attr_reader&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;:scope&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;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="vi"&gt;@user&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
      &lt;span class="vi"&gt;@scope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scope&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;resolve&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;admin?&lt;/span&gt;
        &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="n"&gt;scope&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;published: &lt;/span&gt;&lt;span class="kp"&gt;true&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;def&lt;/span&gt; &lt;span class="nf"&gt;update?&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;admin?&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="ow"&gt;not&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;published?&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;Pundit 会做如下关于这个类 (Scope) 的一些假设&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;类的名字为&lt;code&gt;Scope&lt;/code&gt;并且它嵌套在我们的 policy 类中&lt;/li&gt;
&lt;li&gt;该类的第一个参数是 user，Pundit 将会调用&lt;code&gt;current_user&lt;/code&gt;方法来发送到此参数内&lt;/li&gt;
&lt;li&gt;第二个参数是某种类型的范围，并且可以执行查询。一般来说它是一个&lt;code&gt;ActiveRecord&lt;/code&gt;类或&lt;code&gt;ActiveRecord ::Relation&lt;/code&gt;。他和之前的 policy 中的方法完全是不同的&lt;/li&gt;
&lt;li&gt;该类需要具有&lt;code&gt;resolve&lt;/code&gt;相应方法，它需要返回一些可迭代的结果。如果是&lt;code&gt;ActiveRecord&lt;/code&gt;类通常返回的是&lt;code&gt;ActiveRecord::Relation&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;上面的&lt;code&gt;Scope&lt;/code&gt;可以从&lt;code&gt;ApplicationPolicy&lt;/code&gt;的 Scope 集成&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;PostPolicy&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationPolicy&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Scope&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Scope&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;resolve&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;admin?&lt;/span&gt;
        &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="n"&gt;scope&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;published: &lt;/span&gt;&lt;span class="kp"&gt;true&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;def&lt;/span&gt; &lt;span class="nf"&gt;update?&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;admin?&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="ow"&gt;not&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;published?&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;code&gt;policy_scope&lt;/code&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;
  &lt;span class="c1"&gt;# 返回所有的Post或未发布的Post，根据当前用户判断&lt;/span&gt;
  &lt;span class="vi"&gt;@posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;policy_scope&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Post&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;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;
  &lt;span class="c1"&gt;# 先通过Scope过滤后，在通过传递的id参数进行过滤&lt;/span&gt;
  &lt;span class="vi"&gt;@post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;policy_scope&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;find&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="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&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;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sx"&gt;% policy_scope(@user.posts).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;post&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="sx"&gt;%&amp;gt;
  &amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sx"&gt;%= link_to post.title, post_path(post) %&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="3.3 确保使用了 Policy 和 Scope"&gt;3.3 确保使用了 &lt;code&gt;Policy&lt;/code&gt; 和 &lt;code&gt;Scope&lt;/code&gt;
&lt;/h4&gt;
&lt;p&gt;Pundit 很容易实现我们的程序权限验证，并且 Pundit 引导我们去手动为每个控制器的动作创建权限验证。在这种情况下我们很容忘记给某些控制器动作增加权限。&lt;/p&gt;

&lt;p&gt;幸运的是 Pundit 提供了这样的一个辅助校验，它通过增加一个&lt;code&gt;after_action&lt;/code&gt;钩子，让没有调用&lt;code&gt;authorize&lt;/code&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;ApplicationController&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;Base&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Pundit&lt;/span&gt;
  &lt;span class="c1"&gt;# 通过钩子调用 Pundit 内置的 verify_authorized方法&lt;/span&gt;
  &lt;span class="n"&gt;after_action&lt;/span&gt; &lt;span class="ss"&gt;:verify_authorized&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;同样的 Pundit 还提供了&lt;code&gt;verify_policy_scoped&lt;/code&gt;去校验控制器动作是否调用&lt;code&gt;policy_scope&lt;/code&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;ApplicationController&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;Base&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Pundit&lt;/span&gt;
  &lt;span class="n"&gt;after_action&lt;/span&gt; &lt;span class="ss"&gt;:verify_authorized&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;except: :index&lt;/span&gt;
  &lt;span class="n"&gt;after_action&lt;/span&gt; &lt;span class="ss"&gt;:verify_policy_scoped&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: :index&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;暂时就这么多了哈，这里补充一个我&lt;a href="https://github.com/monsterooo/dpr-example" rel="nofollow" target="_blank" title=""&gt;练习&lt;/a&gt;的仓库地址。&lt;/p&gt;

&lt;p&gt;总结：学习了 Devise、Pundit、Rolify 三个库的基本使用方法。我们可以给我们的程序快速加入用户角色资源访问控制。&lt;/p&gt;

&lt;p&gt;以上的知识点知识我查看和学习文档时所做的记录，如果无法满足你的好奇心请查看对应的 Github 仓库。&lt;/p&gt;

&lt;p&gt;感谢收看&lt;/p&gt;</description>
      <author>monsterooo</author>
      <pubDate>Wed, 03 Jul 2019 15:26:49 +0800</pubDate>
      <link>https://ruby-china.org/topics/38779</link>
      <guid>https://ruby-china.org/topics/38779</guid>
    </item>
    <item>
      <title>Rails 路由学习</title>
      <description>&lt;p&gt;路由相关的类和模块在命名空间 ActionDispatch::Routing::Mapper 中，这里我给一个它的&lt;a href="https://api.rubyonrails.org/files/actionpack/lib/action_dispatch/routing/mapper_rb.html" rel="nofollow" target="_blank" title=""&gt;链接&lt;/a&gt;方便在学习时查看&lt;/p&gt;
&lt;h3 id="match"&gt;match&lt;/h3&gt;
&lt;p&gt;匹配一个 URL 模式到一个或多个路由&lt;/p&gt;

&lt;p&gt;基础使用&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 匹配格式为 :controller/:action. 请注意这样使用路由不能带参数&lt;/span&gt;
&lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="s1"&gt;'account/setting'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;via: :get&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;table class="table table-bordered table-striped"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th&gt;Prefix&lt;/th&gt;
&lt;th&gt;Verb&lt;/th&gt;
&lt;th&gt;URI Pattern&lt;/th&gt;
&lt;th&gt;Controller#Action&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;account_setting&lt;/td&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;/account/setting(.:format)&lt;/td&gt;
&lt;td&gt;account#setting&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;带参数的路由&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 带参数的路由必须指定 :to 参数, 他才能正确匹配到指定的 controller 和 action&lt;/span&gt;
&lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="s1"&gt;'account/setting/:id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"account#setting"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;via: :get&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;table class="table table-bordered table-striped"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th&gt;Prefix&lt;/th&gt;
&lt;th&gt;Verb&lt;/th&gt;
&lt;th&gt;URI Pattern&lt;/th&gt;
&lt;th&gt;Controller#Action&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;/account/setting/:id(.:format)&lt;/td&gt;
&lt;td&gt;account#setting&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;在路由匹配中使用通配符并且映射到&lt;code&gt;params&lt;/code&gt;中&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="s1"&gt;'songs/*category/:title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s1"&gt;'songs#show'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;via: :get&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;table class="table table-bordered table-striped"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th&gt;Prefix&lt;/th&gt;
&lt;th&gt;Verb&lt;/th&gt;
&lt;th&gt;URI Pattern&lt;/th&gt;
&lt;th&gt;Controller#Action&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;/songs/*category/:title(.:format)&lt;/td&gt;
&lt;td&gt;songs#show&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;上面的通配符路由会将&lt;code&gt;songs/rock/classic/stairway-to-heaven&lt;/code&gt;路径做匹配和映射&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;ActionController::Parameters {"controller"=&amp;gt;"songs", "action"=&amp;gt;"show", "category"=&amp;gt;"rock/classic/abc", "title"=&amp;gt;"stairway-to-heaven"} permitted: false&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;路由映射到 controller 和 action 的几种写法&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 短写形式, match的第一个参数传递一个hash用来映射对应的路由和控制器&lt;/span&gt;
&lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="s1"&gt;'photos/:id'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'photos#show'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;via: :get&lt;/span&gt;
&lt;span class="c1"&gt;# 我们上面一直使用的正常模式(比较直观)&lt;/span&gt;
&lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="s1"&gt;'photos/:id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s1"&gt;'photos#show'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;via: :get&lt;/span&gt;
&lt;span class="c1"&gt;# 冗余模式, 所有的参数都通过options来指定&lt;/span&gt;
&lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="s1"&gt;'photos/:id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;controller: &lt;/span&gt;&lt;span class="s1"&gt;'photos'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;action: &lt;/span&gt;&lt;span class="s1"&gt;'show'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;via: :get&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;除了以上&lt;code&gt;match&lt;/code&gt;的几种使用方法外，还可以指定兼容&lt;code&gt;Rack&lt;/code&gt;方式的路由&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="s1"&gt;'photos/:id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Coming soon'&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="ss"&gt;via: :get&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="match options"&gt;match options&lt;/h3&gt;&lt;h4 id=":controller"&gt;:controller&lt;/h4&gt;
&lt;p&gt;路由对应控制器名称&lt;/p&gt;
&lt;h4 id="：action"&gt;：action&lt;/h4&gt;
&lt;p&gt;路由对应控制器里的方法名称&lt;/p&gt;
&lt;h4 id=":param"&gt;:param&lt;/h4&gt;
&lt;p&gt;可以用于覆盖资源默认的&lt;code&gt;:id&lt;/code&gt;参数，一但覆盖你可以在控制的方法中使用&lt;code&gt;params[:param]&lt;/code&gt;去访问&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:photos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;param: :title&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;table class="table table-bordered table-striped"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th&gt;Prefix&lt;/th&gt;
&lt;th&gt;Verb&lt;/th&gt;
&lt;th&gt;URI Pattern&lt;/th&gt;
&lt;th&gt;Controller#Action&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;photos&lt;/td&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;/photos(.:format)&lt;/td&gt;
&lt;td&gt;photos#index&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;POST&lt;/td&gt;
&lt;td&gt;/photos(.:format)&lt;/td&gt;
&lt;td&gt;photos#create&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;new_photo&lt;/td&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;/photos/new(.:format)&lt;/td&gt;
&lt;td&gt;photos#new&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;edit_photo&lt;/td&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;/photos/:title/edit(.:format)&lt;/td&gt;
&lt;td&gt;photos#edit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;photo&lt;/td&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;/photos/:title(.:format)&lt;/td&gt;
&lt;td&gt;photos#show&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;PATCH&lt;/td&gt;
&lt;td&gt;/photos/:title(.:format)&lt;/td&gt;
&lt;td&gt;photos#update&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;PUT&lt;/td&gt;
&lt;td&gt;/photos/:title(.:format)&lt;/td&gt;
&lt;td&gt;photos#update&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;DELETE&lt;/td&gt;
&lt;td&gt;/photos/:title(.:format)&lt;/td&gt;
&lt;td&gt;photos#destroy&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;嗯我们看到之前默认&lt;code&gt;:id&lt;/code&gt;已经被替换为了&lt;code&gt;:title&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;为了更好配合上面路由的使用方法，你还可以覆盖对应模型的&lt;code&gt;to_param&lt;/code&gt;方法，去构造符合路由的 url&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;Photo&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&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;Base&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;to_param&lt;/span&gt;
    &lt;span class="nb"&gt;name&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;photo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Photo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s1"&gt;'ruby-china'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;photo_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;photo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# =&amp;gt; "/photos/ruby-china"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=":path"&gt;:path&lt;/h4&gt;
&lt;p&gt;路由的前缀&lt;/p&gt;
&lt;h4 id=":module"&gt;:module&lt;/h4&gt;
&lt;p&gt;控制器的命名空间，这里暂时还没懂。稍后补上&lt;/p&gt;
&lt;h4 id=":as"&gt;:as&lt;/h4&gt;
&lt;p&gt;设置生成路由辅助函数的名称&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="s2"&gt;"account/setting"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;via: :get&lt;/span&gt;
&lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="s2"&gt;"account_as/setting_as"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;as: &lt;/span&gt;&lt;span class="s1"&gt;'setting'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;via: :get&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;table class="table table-bordered table-striped"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th&gt;Prefix&lt;/th&gt;
&lt;th&gt;Verb&lt;/th&gt;
&lt;th&gt;URIPattern&lt;/th&gt;
&lt;th&gt;Controller#Action&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;account_setting&lt;/td&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;/account/setting(.:format)&lt;/td&gt;
&lt;td&gt;account#setting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;setting&lt;/td&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;/account_as/setting_as(.:format)&lt;/td&gt;
&lt;td&gt;account_as#setting_as&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;通过上面的输出可以看出，我们将&lt;code&gt;account_as/setting_as&lt;/code&gt;路由的生成函数定义为了&lt;code&gt;setting&lt;/code&gt;, 在代码中就可以这样使用&lt;code&gt;setting_url&lt;/code&gt; &lt;code&gt;setting_path&lt;/code&gt;    &lt;/p&gt;
&lt;h4 id=":via"&gt;:via&lt;/h4&gt;
&lt;p&gt;定义路由所匹配的动作 (verbs), 相关动作资料可以看&lt;a href="https://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/HttpHelpers.html" rel="nofollow" target="_blank" title=""&gt;这里&lt;/a&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="s1"&gt;'path'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s1"&gt;'c#a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;via: :get&lt;/span&gt;             &lt;span class="c1"&gt;# get &lt;/span&gt;
&lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="s1"&gt;'path'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s1"&gt;'c#a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;via: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:get&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:post&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;    &lt;span class="c1"&gt;# get/post&lt;/span&gt;
&lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="s1"&gt;'path'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s1"&gt;'c#a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;via: :all&lt;/span&gt;             &lt;span class="c1"&gt;# all http verb&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=":on"&gt;:on&lt;/h4&gt;
&lt;p&gt;可以为 resource(s) 定义的资源增加&lt;code&gt;:member&lt;/code&gt;, &lt;code&gt;:collection&lt;/code&gt;, &lt;code&gt;:new&lt;/code&gt;路由。请注意这个必须在&lt;code&gt;resource(s)&lt;/code&gt;的 do 语句块中使用&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:photos&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="s1"&gt;'preview'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s1"&gt;'photos#preview'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;on: :new&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;via: :get&lt;/span&gt;
  &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="s1"&gt;'preview'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s1"&gt;'photos#preview'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;on: :member&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;via: :get&lt;/span&gt;
  &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="s1"&gt;'preview'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s1"&gt;'photos#preview'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;on: :collection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;via: :get&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;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:photos&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;member&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="s1"&gt;'preview'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s1"&gt;'photos#preview'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;via: :get&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;table class="table table-bordered table-striped"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th&gt;Prefix&lt;/th&gt;
&lt;th&gt;Verb&lt;/th&gt;
&lt;th&gt;URIPattern&lt;/th&gt;
&lt;th&gt;Controller#Action&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;preview_new_photo&lt;/td&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;/photos/new/preview(.:format)&lt;/td&gt;
&lt;td&gt;photos#preview&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;preview_photo&lt;/td&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;/photos/:id/preview(.:format)&lt;/td&gt;
&lt;td&gt;photos#preview&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;preview_photos&lt;/td&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;/photos/preview(.:format)&lt;/td&gt;
&lt;td&gt;photos#preview&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;h4 id=":constraints"&gt;:constraints&lt;/h4&gt;
&lt;p&gt;可以使用正则表达式或者一个可以响应&lt;code&gt;matches?&lt;/code&gt;方法的对象来对参数进行约束&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="s1"&gt;'account/setting/:id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;constraints: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;id: &lt;/span&gt;&lt;span class="sr"&gt;/[A-Z]\d{5}/&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;  &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s1"&gt;'account#setting'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;via: :get&lt;/span&gt; &lt;span class="c1"&gt;# 约束 /account/setting/A12345&lt;/span&gt;
&lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="s1"&gt;'account/setting'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;constraints: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;format: &lt;/span&gt;&lt;span class="s1"&gt;'json'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s1"&gt;'account#setting'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;via: :get&lt;/span&gt; &lt;span class="c1"&gt;# 这个不是太懂!&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Whitelist&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;matches?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote_ip&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'1.2.3.4'&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="s1"&gt;'account/setting'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s1"&gt;'account#setting'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;constraints: &lt;/span&gt;&lt;span class="no"&gt;Whitelist&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;via: :get&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;table class="table table-bordered table-striped"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th&gt;Prefix&lt;/th&gt;
&lt;th&gt;Verb&lt;/th&gt;
&lt;th&gt;URIPattern&lt;/th&gt;
&lt;th&gt;Controller#Action&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;/account/setting/:id(.:format)&lt;/td&gt;
&lt;td&gt;account#setting {:id=&amp;gt;/[A-Z]\d{5}/}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;account_setting&lt;/td&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;/account/setting(.:format)&lt;/td&gt;
&lt;td&gt;account#setting {:format=&amp;gt;"json"}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;preview_photos&lt;/td&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;/account/setting(.:format)&lt;/td&gt;
&lt;td&gt;account#setting&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;h4 id=":defaults"&gt;:defaults&lt;/h4&gt;
&lt;p&gt;设置默认&lt;code&gt;params&lt;/code&gt;的值&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="s1"&gt;'account/setting'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s1"&gt;'account#setting'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;defaults: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;id: &lt;/span&gt;&lt;span class="s1"&gt;'hello'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="ss"&gt;via: :get&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;params 输出：&lt;code&gt;&amp;lt;ActionController::Parameters {"id"=&amp;gt;"hello", "controller"=&amp;gt;"account", "action"=&amp;gt;"setting"} permitted: false&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;总结：以上我们学会了&lt;code&gt;match&lt;/code&gt;方法的基础使用和它的一些选项，在往后的使用中更能得心应手。关于&lt;code&gt;get&lt;/code&gt;, &lt;code&gt;post&lt;/code&gt;, &lt;code&gt;delete&lt;/code&gt;, &lt;code&gt;put&lt;/code&gt;其实也是调用的&lt;code&gt;match&lt;/code&gt;方法&lt;/p&gt;

&lt;p&gt;感谢阅读，&lt;a href="https://github.com/monsterooo/blog/issues/34" rel="nofollow" target="_blank" title=""&gt;原文链接&lt;/a&gt;喜欢可以 star 哈&lt;/p&gt;</description>
      <author>monsterooo</author>
      <pubDate>Wed, 26 Jun 2019 17:23:52 +0800</pubDate>
      <link>https://ruby-china.org/topics/38750</link>
      <guid>https://ruby-china.org/topics/38750</guid>
    </item>
    <item>
      <title>Rails 使用前端 React 框架的相关配置</title>
      <description>&lt;p&gt;在 rails 中使用 React.js 框架相关的配置记录&lt;/p&gt;
&lt;h3 id="目标："&gt;目标：&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;创建基础项目&lt;/li&gt;
&lt;li&gt;配置项目热加载&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="1. 创建基础项目"&gt;1. 创建基础项目&lt;/h3&gt;
&lt;p&gt;首先使用&lt;code&gt;rails new&lt;/code&gt;命令创建一个 rails 的基础项目，完整的命令如下：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rails new railsUseReact --skip-turbolinks --skip-coffee --webpack=react&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;执行上述命令时稍微要等待一会，安装完毕之后即可继续。&lt;/p&gt;
&lt;h3 id="2. 配置项目热加载"&gt;2. 配置项目热加载&lt;/h3&gt;
&lt;p&gt;现在有了一个模板项目，我们需要创建一个路由用于测试。执行如下命令创建一个新的路由：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rails g controller Welcome index&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;接着我们需要开两个控制台，分别在项目根目录执行如下命令&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 控制台1
rails s
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 控制台2
bin/webpack-dev-server
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;浏览器访问：&lt;a href="http://localhost:3000/welcome/index" rel="nofollow" target="_blank"&gt;http://localhost:3000/welcome/index&lt;/a&gt;  可以看到我们创建的页面&lt;/p&gt;

&lt;p&gt;接下来我们先来看看模板项目为我们创建的一个 javascript 目录，它用来存放 React.js 组件相关的代码：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➜  railsUseReact git:(master) ✗ tree app/javascript
app/javascript
└── packs
    ├── application.js
    └── hello_react.jsx # 这里是一个React组件我们会使用它
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后修改&lt;code&gt;app/views/welcome/index.html.erb&lt;/code&gt;使用&lt;code&gt;javascript_pack_tag&lt;/code&gt;加载我们的 hello_react 组件，代码如下：&lt;/p&gt;

&lt;p&gt;文件：app/views/welcome/index.html.erb&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;h1&amp;gt;Welcome#index&amp;lt;/h1&amp;gt;
&amp;lt;%= javascript_pack_tag 'hello_react' %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;刷新浏览器我们可以看到如下的输出：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Welcome#index
Hello React!
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;以上的修改可以查看&lt;a href="https://github.com/monsterooo/railsUseReact/commit/779d5163159fb4b7113b2bd47f8a0f06c7e4ffe3" rel="nofollow" target="_blank" title=""&gt;提交记录&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;接着我们需要来对&lt;code&gt;app/javascript/packs/hello_react.jsx&lt;/code&gt;组件进行一些改动，&lt;code&gt;hello_react.jsx&lt;/code&gt;只保留入口组件。我们把真正的 Hello 组件单独存放。&lt;/p&gt;

&lt;p&gt;创建如下的目录和文件：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➜  railsUseReact git:(master) ✗ tree app/javascript
app/javascript
├── components
│&amp;nbsp;&amp;nbsp; └── Hello
│&amp;nbsp;&amp;nbsp;     ├── index.js
│&amp;nbsp;&amp;nbsp;     └── style.css
└── 其他文件
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;修改 Hello 组件为如下的内容：&lt;/p&gt;

&lt;p&gt;文件：app/javascript/components/Hello/index.js&lt;/p&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prop-types&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./style.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Hello&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defaultProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;David&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;propTypes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;文件：app/javascript/packs/hello_react.jsx&lt;/p&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Hello&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../components/Hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DOMContentLoaded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Hello&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"React"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;再次刷新浏览器可以看到如下内容：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Welcome#index
Hello React!
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;一切工作正常，接下来就配置&lt;a href="https://github.com/rails/webpacker/blob/master/docs/webpack-dev-server.md" rel="nofollow" target="_blank" title=""&gt;热加载&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;启动 webpack 热加载&lt;/p&gt;

&lt;p&gt;文件：config/webpacker.yml&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dev_server:
  hmr: true # 这里修改为true即可启动热加载
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后我们需要更新&lt;code&gt;hello_react.jsx&lt;/code&gt;组件里面的内容使热加载是可以重新渲染组件&lt;/p&gt;

&lt;p&gt;文件：app/javascript/packs/hello_react.jsx&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react'
import ReactDOM from 'react-dom'
import Hello from '../components/Hello';

const renderApp = (Component) =&amp;gt; {
  ReactDOM.render(
    &amp;lt;Component name="React" /&amp;gt;,
    document.body.appendChild(document.createElement('div')),
  )
}
document.addEventListener('DOMContentLoaded', () =&amp;gt; {
  renderApp(Hello);
})

if (process.env.NODE_ENV !== 'production' &amp;amp;&amp;amp; module.hot) {
  module.hot.accept('../components/Hello', () =&amp;gt; {
    const NextHello = require('../components/Hello').default;
    renderApp(NextHello);
  });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;接着安装&lt;code&gt;react-hot-loader&lt;/code&gt;包来自动进行热替换，命令如下：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./bin/yarn add react-hot-loader
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后修改我们的&lt;code&gt;Hello&lt;/code&gt;组件使用 react-hot-loader 包装&lt;/p&gt;

&lt;p&gt;文件：app/javascript/components/Hello/index.js&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import PropTypes from 'prop-types';
import { hot } from 'react-hot-loader';
import './style.css';

class Hello extends React.Component {
  render() {
    return (
      &amp;lt;div className="hello"&amp;gt;Hello {this.props.name}!123&amp;lt;/div&amp;gt;
    )
  }
}

Hello.defaultProps = {
  name: 'David'
}

Hello.propTypes = {
  name: PropTypes.string
}

export default hot(module)(Hello);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;重启服务，然后再次访问一些正常。你可以尝试修改一下&lt;code&gt;app/javascript/components/Hello/index.js&lt;/code&gt;组件的内容比如如下代码，可以通过 Chrome 调试中的 Network 查看页面并没有刷新然后组件的数据已经重新加载过了&lt;/p&gt;

&lt;p&gt;以上的修改可以查看&lt;a href="https://github.com/monsterooo/railsUseReact/commit/80941a399584c2a3a1d86ed4cc4ce32730cfe0d6" rel="nofollow" target="_blank" title=""&gt;提交记录&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;整个配置完毕，感谢收看&lt;/p&gt;</description>
      <author>monsterooo</author>
      <pubDate>Wed, 12 Jun 2019 00:32:20 +0800</pubDate>
      <link>https://ruby-china.org/topics/38631</link>
      <guid>https://ruby-china.org/topics/38631</guid>
    </item>
    <item>
      <title>Ruby 学习笔记</title>
      <description>&lt;h2 id="Ruby常用知识记录"&gt;Ruby 常用知识记录&lt;/h2&gt;&lt;h4 id="语法"&gt;语法&lt;/h4&gt;
&lt;p&gt;* ||= 或者等于运算符&lt;/p&gt;

&lt;p&gt;* **= 产生一个 2 次方&lt;/p&gt;

&lt;p&gt;* &amp;amp;= “与”位算符&lt;/p&gt;

&lt;p&gt;* |= “或”位运算&lt;/p&gt;

&lt;p&gt;* ^= “异或”位运算&lt;/p&gt;

&lt;p&gt;* %= 模运算&lt;/p&gt;

&lt;p&gt;* &amp;amp;&amp;amp;= 与等运算 (极少使用)&lt;/p&gt;

&lt;p&gt;Object.ancestors # Object 类的祖先&lt;/p&gt;
&lt;h4 id="类"&gt;类&lt;/h4&gt;
&lt;p&gt;self.class 指向类对象&lt;/p&gt;
&lt;h4 id="方法记录"&gt;方法记录&lt;/h4&gt;
&lt;p&gt;BasicObject.method_missing  # 当对象不能相应消息时会调用此方法&lt;/p&gt;

&lt;p&gt;Kernel.private_instance_methods.sort # 查看 Kernel 提供的所有私有实例方法&lt;/p&gt;

&lt;p&gt;String.methods # 继承和单例方法 (实例方法和单例方法)&lt;/p&gt;

&lt;p&gt;Obj.singleton_methods # 只能查看对象的单例方法&lt;/p&gt;

&lt;p&gt;String.instance_methods # 查看对象拥有的所有实例方法&lt;/p&gt;

&lt;p&gt;Obj.methods.include?(:concat) # 查看对象是否拥有某方法&lt;/p&gt;

&lt;p&gt;String.instance_methods(false).sort # 查看类不包含祖先的实例方法的集合&lt;/p&gt;

&lt;p&gt;String.private_methods # 查看所有私有方法&lt;/p&gt;

&lt;p&gt;String.public_methods # 查看所有公有方法&lt;/p&gt;

&lt;p&gt;String.protected_methods # 查看所有保护方法&lt;/p&gt;

&lt;p&gt;类和模块&lt;/p&gt;

&lt;p&gt;MyClass.private_instance_methods # 私有方法&lt;/p&gt;

&lt;p&gt;MyClass.protected_instance_methods # 保护方法&lt;/p&gt;

&lt;p&gt;MyClass.public_instance_methods # 公有方法&lt;/p&gt;

&lt;p&gt;public_instance_methods 等于  instance_methods&lt;/p&gt;

&lt;p&gt;Obj.respond_to?(:to_ary) # Obj 对象是否可以相应&lt;code&gt;:to_ary&lt;/code&gt;方法&lt;/p&gt;
&lt;h4 id="方法"&gt;方法&lt;/h4&gt;
&lt;p&gt;具名参数，可以指定参数的名称&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;m&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:)&lt;/span&gt;
    &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;a: &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;b: &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 1, 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="内置 to_* 方法"&gt;内置 to_* 方法&lt;/h4&gt;
&lt;p&gt;* to_s 转换为字符串&lt;/p&gt;

&lt;p&gt;* to_a 转换为数组，它会自动与&lt;code&gt;*&lt;/code&gt;运算符捆绑&lt;/p&gt;

&lt;p&gt;* to_i 字符串到整型&lt;/p&gt;

&lt;p&gt;* to_f 字符串到浮点型&lt;/p&gt;

&lt;p&gt;* to_str 当一个对象可以相应&lt;code&gt;to_str&lt;/code&gt;方法，那么当对象呗用作 String#+ 的参数时，它自己的&lt;code&gt;to_str&lt;/code&gt;的表现形式将会启用&lt;/p&gt;

&lt;p&gt;* to_ary 对象如果有&lt;code&gt;to_ary&lt;/code&gt;方法它就可以伪装成一个数组，一旦对象在仅作为数组的地方使用，&lt;code&gt;to_ary&lt;/code&gt;将会被调用&lt;/p&gt;
&lt;h4 id="常用语/法糖"&gt;常用语/法糖&lt;/h4&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&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;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="n"&gt;my_object&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;my_other_object&lt;/span&gt;
&lt;span class="c1"&gt;# 只要有+方法自动也获得 x += 2 语法糖方法&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;自定义一元运算符&lt;/p&gt;

&lt;p&gt;通过定义&lt;code&gt;+@&lt;/code&gt;和&lt;code&gt;-@&lt;/code&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;Banner&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;+@&lt;/span&gt;
        &lt;span class="c1"&gt;# code&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;-@&lt;/span&gt;
        &lt;span class="c1"&gt;# code&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;banner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Banner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;banner&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;banner&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;也可以定义&lt;code&gt;!&lt;/code&gt;方法来定义&lt;code&gt;!&lt;/code&gt;(逻辑否定) 运算符，但是他会影响一元运算符&lt;code&gt;!&lt;/code&gt;和&lt;code&gt;not&lt;/code&gt;。代表着&lt;code&gt;!&lt;/code&gt;和&lt;code&gt;not&lt;/code&gt;会执行到定义的&lt;code&gt;!&lt;/code&gt;的方法&lt;/p&gt;

&lt;p&gt;分离数组&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'123'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'456'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="c1"&gt;# a = '123' b = '456'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="bang(!)方法和”危险”"&gt;bang(!) 方法和”危险”&lt;/h4&gt;
&lt;p&gt;方法以&lt;code&gt;!&lt;/code&gt;结尾的称谓 bang 方法。这样的方法被标记为有”危险”的方法。&lt;/p&gt;
&lt;h4 id="字符串引用机制"&gt;字符串引用机制&lt;/h4&gt;
&lt;p&gt;除了传统的字符串引用之外，还有另外一种引用格式为：&lt;code&gt;%char{text}&lt;/code&gt;方式，&lt;code&gt;char&lt;/code&gt;是一个特殊字符。&lt;/p&gt;

&lt;p&gt;* %q{abc} # 同单引号&lt;/p&gt;

&lt;p&gt;* %Q{ab#{var}c} # 同双引号&lt;/p&gt;

&lt;p&gt;* %{ab#{var}c} # 同双引号&lt;/p&gt;

&lt;p&gt;* %限定符号可以使用任意字符，只要两边能够匹配即可。还有限定符不能由字母组成&lt;/p&gt;
&lt;h4 id="here文档"&gt;here 文档&lt;/h4&gt;
&lt;p&gt;如果要进入 here-doc 使用&lt;code&gt;&amp;lt;&amp;lt;&lt;/code&gt;运算符即可，分割字符串可以是任何字符。这里结尾的&lt;code&gt;EOM&lt;/code&gt;必须是左对齐。如下所示：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOM&lt;/span&gt;&lt;span class="sh"&gt;
这是一段文本
EOM # 这里的EOM必须是左对齐
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可以在&lt;code&gt;&amp;lt;&amp;lt;&lt;/code&gt;后使用&lt;code&gt;-&lt;/code&gt;连字符关闭结尾必须左对齐模式&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class="no"&gt;EOM&lt;/span&gt;&lt;span class="sh"&gt;
这是一段文本
    EOM # 这里的EOM可以不左对齐
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;默认情况 here-doc 使用双引号限定 (可以使用插值支字符串)，如果想要使用单引号限定可以在开始的&lt;code&gt;EOM&lt;/code&gt;使用单引号包裹起来&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;'EOM'&lt;/span&gt;&lt;span class="sh"&gt;
文本 &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;
&lt;/span&gt;&lt;span class="no"&gt;EOM&lt;/span&gt;
&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; "文本 \#{n}\n"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;&amp;lt;EOM&lt;/code&gt;作为占位符服务于即将出现的 here 文档。理解为&lt;code&gt;&amp;lt;&amp;lt;EOM&lt;/code&gt;之后的字符串将会替换为&lt;code&gt;&amp;lt;&amp;lt;EOM&lt;/code&gt;所在的占位符。然后在&lt;code&gt;&amp;lt;&amp;lt;EOM&lt;/code&gt;之后还是可以接方法调用，示例如下：&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="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;&lt;span class="sh"&gt;
5
&lt;/span&gt;&lt;span class="no"&gt;EOM&lt;/span&gt;
&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;通过上面对占位符的理解我们可以在字面对象构造中使用 here 文档，示例如下：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="sh"&gt;
这是here-doc!
&lt;/span&gt;&lt;span class="no"&gt;EOM&lt;/span&gt;
&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; [1, 2, 3, "这是here-doc!\n", 4]&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;do_something&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;do_something&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOM&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;
我是第三个参数
&lt;/span&gt;&lt;span class="no"&gt;EOM&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="字符串基本操作"&gt;字符串基本操作&lt;/h4&gt;
&lt;p&gt;string[]，[] 是一个方法调用&lt;/p&gt;

&lt;p&gt;* string[1]&lt;/p&gt;

&lt;p&gt;* string[-1]&lt;/p&gt;

&lt;p&gt;* string[1..5]&lt;/p&gt;

&lt;p&gt;* string[-12..-3]&lt;/p&gt;

&lt;p&gt;* string[‘search text’] # 搜索字符串，有返回搜索字符串，无返回 nil&lt;/p&gt;

&lt;p&gt;* string[/abc/] # 正则搜索&lt;/p&gt;

&lt;p&gt;* &lt;/p&gt;
&lt;h4 id="符号"&gt;符号&lt;/h4&gt;
&lt;p&gt;符号常用的创建方式：&lt;/p&gt;

&lt;p&gt;* :abc&lt;/p&gt;

&lt;p&gt;* :”abc”&lt;/p&gt;

&lt;p&gt;* “abc”.to_sym&lt;/p&gt;

&lt;p&gt;* “abc”.intern&lt;/p&gt;

&lt;p&gt;符号主要特点：&lt;/p&gt;

&lt;p&gt;* 不变型：符号一旦创建不能修改。不能：&lt;code&gt;:abc &amp;lt;&amp;lt; :d&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;* 唯一性：不论在合适 &lt;code&gt;:abc&lt;/code&gt;都是同一个对象
符号主要用途：&lt;/p&gt;

&lt;p&gt;* 作为方法参数：&lt;/p&gt;

&lt;p&gt;* 如类对象方法 &lt;code&gt;attr_accessor :name&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;* 消息发送 &lt;code&gt;“abc”.send(:upcase)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;* 作为散列键：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ruby
                # 符号键
                hash = { :name =&amp;gt; ‘monsterooo’ }
                hash[:name]
                # 符号键可以简写
                hash = { name: ‘monsterooo’ }
                hash[:name]
                # 字符串键
                hash = { ‘name’ =&amp;gt; ‘monsterooo’ }
                hash[‘name’]
&lt;/code&gt;&lt;/p&gt;
&lt;h4 id="数值对象"&gt;数值对象&lt;/h4&gt;&lt;h4 id="日期和时间"&gt;日期和时间&lt;/h4&gt;
&lt;p&gt;日期和时间通过这 3 个类来操作：&lt;code&gt;Time&lt;/code&gt;、&lt;code&gt;Date&lt;/code&gt;、&lt;code&gt;DateTime&lt;/code&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 提供Date和DateTime类&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'date'&lt;/span&gt;
&lt;span class="c1"&gt;# 增强Time类&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'time'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;日期常用操作：&lt;/p&gt;

&lt;p&gt;* Date.today
        #  &lt;/p&gt;

&lt;p&gt;* Date.today.to_s # 2019-01-19&lt;/p&gt;

&lt;p&gt;* Date.new(1999, 1, 1) # 传递年、月、日创建对象&lt;/p&gt;

&lt;p&gt;* Date.parse(‘2008/8/8’) # 通过字符串构造&lt;/p&gt;

&lt;p&gt;时间对象常用操作&lt;/p&gt;

&lt;p&gt;* Time.new # 表示当前时间对象&lt;/p&gt;

&lt;p&gt;* Time.now # 和&lt;code&gt;Time.new&lt;/code&gt;相同&lt;/p&gt;

&lt;p&gt;* Time.at(100000000) # 返回从新时代 (格林威治标准时间) 的时间点，加上以秒为单位的参数后构建时间对象&lt;/p&gt;

&lt;p&gt;* Time.mktime(2018, 8, 8,  1, 2, 3) # 使用合理的默认值填充时间，月、日填充 1，小时、分钟、秒填充 0&lt;/p&gt;

&lt;p&gt;* Time.parse('March 22, 1985, 10:32 PM') # 先&lt;code&gt;require ‘time’&lt;/code&gt;，解析成时间&lt;/p&gt;

&lt;p&gt;日期/时间对象&lt;/p&gt;

&lt;p&gt;DateTime 是 Date 的子集，由于重载的关系，它的参数有一点不同&lt;/p&gt;

&lt;p&gt;* DateTime.new(2019, 1, 2, 3, 4, 5) # 指定时间创建日期时间对象&lt;/p&gt;

&lt;p&gt;* DateTime.now # 构造当前日期时间对象&lt;/p&gt;

&lt;p&gt;* DateTime.parse # 解析日期时间
    日期和时间对象提供了很多有用的方法，如下所示：&lt;/p&gt;

&lt;p&gt;* dt = DateTime.now&lt;/p&gt;

&lt;p&gt;* dt.year # 2019&lt;/p&gt;

&lt;p&gt;* dt.hour # 2&lt;/p&gt;

&lt;p&gt;* dt.minute # 26&lt;/p&gt;

&lt;p&gt;* dt.second # 36  注意：Time 对象是&lt;code&gt;t.sec&lt;/code&gt;Time 对象并没有&lt;code&gt;second&lt;/code&gt;方法&lt;/p&gt;

&lt;p&gt;* dt.monday? # 判断是否为一周的某一天&lt;/p&gt;

&lt;p&gt;* dt.leap? # 是否为闰年&lt;/p&gt;

&lt;p&gt;日期时间格式化方法&lt;/p&gt;

&lt;p&gt;所有的日期时间对象都有&lt;code&gt;strftime&lt;/code&gt;方法，可以用来更灵活的格式化时间。格式化字符如下所示：&lt;/p&gt;
&lt;h4 id="数组"&gt;数组&lt;/h4&gt;
&lt;p&gt;新建数组方法：&lt;/p&gt;

&lt;p&gt;* Array.new&lt;/p&gt;

&lt;p&gt;a = Array.new&lt;/p&gt;

&lt;p&gt;Array.new(3) # [nil, nil, nil]&lt;/p&gt;

&lt;p&gt;Array.new(3, ‘abc’) # [‘’abc, ‘abc’, ‘abc’]&lt;/p&gt;

&lt;p&gt;Array.new(3) { n += 1; n * 10 } # [10, 20, 30]&lt;/p&gt;

&lt;p&gt;* []&lt;/p&gt;

&lt;p&gt;* Array 顶层方法&lt;/p&gt;

&lt;p&gt;接收一个参数，如果参数对象拥有&lt;code&gt;to_ary&lt;/code&gt;方法，Array 则会调用该对象的这个方法来生成一个数组。如果&lt;code&gt;to_ary&lt;/code&gt;不存在会尝试调用&lt;code&gt;to_a&lt;/code&gt;方法。如果&lt;code&gt;to_a&lt;/code&gt;方法不存在 Array 会将该对象包装到数组中然后返回它：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ruby
        string = 'A string'
                p string.respond_to?(:to_ary) # false
                p Array(string) # ["A string"]
                def string.to_a
                  split(//)
                end
                p Array(string) # string能相应to_ary方法 ["A", " ", "s", "t", "r", "i", "n", "g"]
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;* &lt;code&gt;%W{}&lt;/code&gt;和&lt;code&gt;%i{}&lt;/code&gt;符号&lt;/p&gt;

&lt;p&gt;&lt;code&gt;%W{}&lt;/code&gt;和&lt;code&gt;%w{}&lt;/code&gt;都会使用空格分割符号里面的字符串，不同的是&lt;code&gt;%W{}&lt;/code&gt;可以使用字符串插值 (双引号字符串)，而&lt;code&gt;%w{}&lt;/code&gt;是单引号字符串。他们都会创建一个数组字符串&lt;/p&gt;

&lt;p&gt;&lt;code&gt;%I{}&lt;/code&gt;和&lt;code&gt;%i{}&lt;/code&gt;类似，只是他们创建的是符号数组&lt;/p&gt;

&lt;p&gt;数组转换方法&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&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;try_convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# nil&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_ary&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&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;try_convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# [1, 2, 3]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;数组方法&lt;/p&gt;

&lt;p&gt;* arr.unshift(‘monster’) # 数组开头添加一个元素&lt;/p&gt;

&lt;p&gt;* arr.push(‘monster’) # 数组末尾添加一个元素 (一次性可加多个)&lt;/p&gt;

&lt;p&gt;* arr &amp;lt;&amp;lt; ‘monster’ # 数组末尾添加一个元素 (只能加一个)&lt;/p&gt;

&lt;p&gt;* arr.shift() # 数组开端移除一个元素&lt;/p&gt;

&lt;p&gt;* arr.pop # 数组尾端移除一个元素&lt;/p&gt;

&lt;p&gt;* arr.concat(arr2) # 合并两个数组，arr 数组会被改变&lt;/p&gt;

&lt;p&gt;* arr.replace(arr2) # 将数组 arr 替换为数组 arr2&lt;/p&gt;

&lt;p&gt;* [1,2,[3,4]].flatten # 将数组扁平化为：[1, 2, 3, 4]&lt;/p&gt;

&lt;p&gt;* [1,2,3].reverse # 将数组反制为：[3, 2, 1]&lt;/p&gt;

&lt;p&gt;* [1,2,3].join(',') # 将数组串联起来，参数是数组之间分隔符&lt;/p&gt;

&lt;p&gt;* [1,2,'a'] * '-' # 同上串联数组 "1-2-a"&lt;/p&gt;

&lt;p&gt;* [1,2,3,2,1].uniq # 去重&lt;/p&gt;

&lt;p&gt;* [1,nil,3].compact # 去除数组中包含 nil 的元素&lt;/p&gt;

&lt;p&gt;* arr.size # 获取长度同&lt;code&gt;arr.length&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;* a.empty? # 如果不包含任何元素返回 true，否则返回 false&lt;/p&gt;

&lt;p&gt;* a.include?(item) # 数组是否包含指定的元素&lt;/p&gt;

&lt;p&gt;* a.count(item) # item 在数组出现的次数&lt;/p&gt;

&lt;p&gt;* a.first(n = 1) # 数组中第前 n 个元素&lt;/p&gt;

&lt;p&gt;* a.last(n = 1) # 数组中末尾 n 个元素&lt;/p&gt;

&lt;p&gt;* a.sample(n = 1) # 返回数组中任意的 n 个元素 (随机)&lt;/p&gt;
&lt;h4 id="散列"&gt;散列&lt;/h4&gt;
&lt;p&gt;创建散列的方式：&lt;/p&gt;

&lt;p&gt;* {}
            * h = {}&lt;/p&gt;

&lt;p&gt;* Hash.new
            * h = Hash.new # 创建空的 hash 对象&lt;/p&gt;

&lt;p&gt;* Hash.[]
            * Hash['a','b'] # {"a"=&amp;gt;"b"}&lt;/p&gt;

&lt;p&gt;* Hash 顶层方法&lt;/p&gt;

&lt;p&gt;* Hash([]) # 传递 [] 返回空的 hash&lt;code&gt;{}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;* Hash(nil) # 同上返回空的 hash&lt;code&gt;{}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;* 如果传递对象，则会调用对象的&lt;code&gt;to_hash&lt;/code&gt;方法&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ruby
            a = 'abc'
            def a.to_hash
              return {value: self}
            end
            p Hash(a) # {:value=&amp;gt;"abc"}
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;添加键值对到散列&lt;/p&gt;

&lt;p&gt;添加键值对和数组使用相同的技术：[]=加语法糖形式，要添加一个状态到 state_hahs，可以使用&lt;code&gt;state_hash[’name’] = ‘monster’&lt;/code&gt;它是&lt;code&gt;state_hash.[] = (‘name’, ‘monster’)&lt;/code&gt;的语法糖形式。也可以使用&lt;code&gt;store&lt;/code&gt;来执行相同操作。&lt;code&gt;state_hash.store('name', 'monster’)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;从散列取值&lt;/p&gt;

&lt;p&gt;* state_hash[‘name’]&lt;/p&gt;

&lt;p&gt;* state_hash.fetch(‘name’)&lt;/p&gt;

&lt;p&gt;* state_hash.values_at(‘val1’, ‘val2’) # 取多个值&lt;/p&gt;

&lt;p&gt;指定默认的散列值和行为&lt;/p&gt;

&lt;p&gt;* 默认情况下不存在的散列返回的是&lt;code&gt;nil&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;h = Hash.new&lt;/p&gt;

&lt;p&gt;h[’no such key’] # nil&lt;/p&gt;

&lt;p&gt;* 可以给&lt;code&gt;Hash.new&lt;/code&gt;的参数指定不同的默认值&lt;/p&gt;

&lt;p&gt;h = Hash.new(0)&lt;/p&gt;

&lt;p&gt;h[‘no such key’] # 0&lt;/p&gt;

&lt;p&gt;* 定义获取不存在键的行为&lt;/p&gt;

&lt;p&gt;h = Hash.new { |hash, key| hash[key] = 0 }&lt;/p&gt;

&lt;p&gt;p h['a'] # 0&lt;/p&gt;

&lt;p&gt;合并散列&lt;/p&gt;

&lt;p&gt;* 合并散列破坏性&lt;/p&gt;

&lt;p&gt;h1 = {"name" =&amp;gt; 'monster'}&lt;/p&gt;

&lt;p&gt;h2 = {"job" =&amp;gt; "web dev"}&lt;/p&gt;

&lt;p&gt;p h1.update(h2) # 合并了两个散列，破坏性&lt;code&gt;h1&lt;/code&gt;会被更新 {“name"=&amp;gt;"monster", "job"=&amp;gt;"web dev"}&lt;/p&gt;

&lt;p&gt;* 非破坏性合并&lt;/p&gt;

&lt;p&gt;h1 = {"name" =&amp;gt; 'monster'}&lt;/p&gt;

&lt;p&gt;h2 = {"job" =&amp;gt; "web dev"}&lt;/p&gt;

&lt;p&gt;p h1.merge(h2) # h1 不会被更改&lt;/p&gt;

&lt;p&gt;从散列中选择和丢弃元素&lt;/p&gt;

&lt;p&gt;* &lt;code&gt;select&lt;/code&gt;获得子散列&lt;/p&gt;

&lt;p&gt;如果代码块返回 true 则保留元素&lt;/p&gt;

&lt;p&gt;h = Hash[1,2,3,4,5,6]&lt;/p&gt;

&lt;p&gt;p h.select { |k,v| k &amp;gt; 3} # {5=&amp;gt;6}&lt;/p&gt;

&lt;p&gt;* &lt;code&gt;reject&lt;/code&gt;丢弃元素&lt;/p&gt;

&lt;p&gt;如果代码块返回 true 则丢弃元素&lt;/p&gt;

&lt;p&gt;h = Hash[1,2,3,4,5,6]&lt;/p&gt;

&lt;p&gt;p h.reject { |k,v| k &amp;gt; 3}&lt;/p&gt;

&lt;p&gt;清楚散列&lt;/p&gt;

&lt;p&gt;* {1 =&amp;gt; ‘one’}.clear # {}&lt;/p&gt;

&lt;p&gt;查询散列&lt;/p&gt;

&lt;p&gt;* h.has_key?(1) # 有键为 1 返回 true&lt;/p&gt;

&lt;p&gt;* h.include?(1) # 类似 has_key&lt;/p&gt;

&lt;p&gt;* h.key?(1) # 类似 has_key&lt;/p&gt;

&lt;p&gt;* h.member?(1) # 类似 has_key&lt;/p&gt;

&lt;p&gt;* h.has_value?(‘three’) # 如果有值为 three 返回 true&lt;/p&gt;

&lt;p&gt;* h.value?(‘three’) # 类似 has_value?&lt;/p&gt;

&lt;p&gt;* h.empty? # 没有任何键值对返回 true&lt;/p&gt;

&lt;p&gt;* h.size # 键值对数量&lt;/p&gt;

&lt;p&gt;散列作为方法最后的参数&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="c1"&gt;# 调用方式1&lt;/span&gt;
&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'monsterooo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="ss"&gt;state: &lt;/span&gt;&lt;span class="s1"&gt;'China'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;job: &lt;/span&gt;&lt;span class="s1"&gt;'dev'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="c1"&gt;# {:state=&amp;gt;"China", :job=&amp;gt;"dev"}&lt;/span&gt;
&lt;span class="c1"&gt;# 如果最后一个参数是散列，那么可以直接在参数最后放置键值对模式&lt;/span&gt;
&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'monsterooo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;state: &lt;/span&gt;&lt;span class="s1"&gt;'China'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;job: &lt;/span&gt;&lt;span class="s1"&gt;'dev'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# {:state=&amp;gt;"China", :job=&amp;gt;"dev"}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="Enumerable和Enumerator集合类型核心"&gt;Enumerable 和 Enumerator 集合类型核心&lt;/h4&gt;
&lt;p&gt;#Ruby/知识记录&lt;/p&gt;

&lt;p&gt;以上是我学习 Ruby 的笔记。后面还会更新 &lt;img title=":no_mouth:" alt="😶" src="https://twemoji.ruby-china.com/2/svg/1f636.svg" class="twemoji"&gt; &lt;/p&gt;</description>
      <author>monsterooo</author>
      <pubDate>Fri, 18 Jan 2019 02:03:50 +0800</pubDate>
      <link>https://ruby-china.org/topics/38016</link>
      <guid>https://ruby-china.org/topics/38016</guid>
    </item>
    <item>
      <title>关于使用 Postgres 的疑问</title>
      <description>&lt;h2 id="新手疑问"&gt;新手疑问&lt;/h2&gt;
&lt;p&gt;为何我看到 ruby 社区中，大多数人都是使用的 Postgres 数据库。而 Mysql 则很少见到。&lt;/p&gt;

&lt;p&gt;这是有什么原因么。&lt;img title=":grinning:" alt="😀" src="https://twemoji.ruby-china.com/2/svg/1f600.svg" class="twemoji"&gt; &lt;/p&gt;</description>
      <author>monsterooo</author>
      <pubDate>Fri, 18 Jan 2019 02:02:10 +0800</pubDate>
      <link>https://ruby-china.org/topics/38015</link>
      <guid>https://ruby-china.org/topics/38015</guid>
    </item>
    <item>
      <title>关于 Ruby 部署的一些疑问</title>
      <description>&lt;p&gt;想知道我们的 ruby-china 是自己的服务器部署的吗？&lt;/p&gt;

&lt;p&gt;还有 heroku 部署是不是在国内不行，因为墙的原因？&lt;/p&gt;</description>
      <author>monsterooo</author>
      <pubDate>Tue, 09 Oct 2018 13:05:47 +0800</pubDate>
      <link>https://ruby-china.org/topics/37601</link>
      <guid>https://ruby-china.org/topics/37601</guid>
    </item>
    <item>
      <title>整理了一下 Rails 常用命令</title>
      <description>&lt;p&gt;正在学习 rails 中&lt;img title=":no_mouth:" alt="😶" src="https://twemoji.ruby-china.com/2/svg/1f636.svg" class="twemoji"&gt; , 一切都是懵懵懂懂，跟着官方文档过了一下常用命令并做了一下整理。欢迎补充&lt;/p&gt;
&lt;h4 id="脚手架"&gt;脚手架&lt;/h4&gt;
&lt;p&gt;bin/rails generate scaffold&lt;/p&gt;

&lt;p&gt;用于生成 rails 中的一整套资源，其中包括 model、controller、erb、helper、test、js、css. 一般这个用于新建一整套页面的时候使用&lt;/p&gt;
&lt;h4 id="控制器生成器"&gt;控制器生成器&lt;/h4&gt;
&lt;p&gt;它用于生成我们需要的控制器，使用的标准格式如下&lt;/p&gt;

&lt;p&gt;bin/rails generate controller NAME [action action] [options]&lt;/p&gt;

&lt;p&gt;[actions action] 用于指定多个动作比如下所示&lt;/p&gt;

&lt;p&gt;bin/rails generate controller Test action1 action2&lt;/p&gt;

&lt;p&gt;它还有一些可选参数用于跳过创建指定文件&lt;/p&gt;
&lt;h4 id="数据迁移(migrate)"&gt;数据迁移 (migrate)&lt;/h4&gt;
&lt;p&gt;用于把 rails 中的模型应用到数据中，这里会执行一些 ruby 代码用来创建数据库模型。&lt;/p&gt;

&lt;p&gt;bin/rails db:migrate&lt;/p&gt;
&lt;h4 id="单元测试"&gt;单元测试&lt;/h4&gt;
&lt;p&gt;关于单元测试详细&lt;a href="http://guides.rubyonrails.org/testing.html" rel="nofollow" target="_blank" title=""&gt;资料&lt;/a&gt;&lt;/p&gt;
&lt;h4 id="测试"&gt;测试&lt;/h4&gt;
&lt;p&gt;bin/rails test 运行所有测试&lt;/p&gt;
&lt;h4 id="服务"&gt;服务&lt;/h4&gt;
&lt;p&gt;下面命令可以启动一个服务来运行我们的 rails 项目&lt;/p&gt;

&lt;p&gt;bin/rails server&lt;/p&gt;
&lt;h4 id="rails 控制台"&gt;rails 控制台&lt;/h4&gt;
&lt;p&gt;控制台可以对 rails 进行一些调试工作，使用 rails 控制就像使用 irb 一样。只不过它加载了当然的 rails 应用进去。是你可以调用到 rails 相关的对象&lt;/p&gt;

&lt;p&gt;bin/rails console&lt;/p&gt;

&lt;p&gt;通过下面的参数你还能指定控制台所在的运行环境&lt;/p&gt;

&lt;p&gt;bin/rails console -e staging&lt;/p&gt;

&lt;p&gt;如果你不想在 rails 中的更改应用到数据库种，可以使用沙箱模式&lt;/p&gt;

&lt;p&gt;bin/rails console --sandbox&lt;/p&gt;
&lt;h4 id="rails 数据库控制台"&gt;rails 数据库控制台&lt;/h4&gt;
&lt;p&gt;它可以使用进入你正在使用数据库的控制台命令行界面，他能支持 MySql、PostgreSQL、SQLite3&lt;/p&gt;

&lt;p&gt;bin/rails dbconsole 或 bin/rails db&lt;/p&gt;
&lt;h4 id="rails runner"&gt;rails runner&lt;/h4&gt;
&lt;p&gt;它可以在 rails 环境中运行某个 ruby 代码的 rails 实例&lt;/p&gt;

&lt;p&gt;bin/rails runner "Model.long_running_method"&lt;/p&gt;

&lt;p&gt;可以使用-e 来指定特定的环境&lt;/p&gt;

&lt;p&gt;bin/rails runner -e staging "Model.long_running_method"&lt;/p&gt;

&lt;p&gt;执行某个 ruby 代码&lt;/p&gt;

&lt;p&gt;bin/rails runner lib/code_to_be_run.rb&lt;/p&gt;
&lt;h4 id="rails destroy"&gt;rails destroy&lt;/h4&gt;
&lt;p&gt;destroy 为 generate 的反面，它用于摧毁 generate 创建的文件&lt;/p&gt;

&lt;p&gt;bin/rails generate model Oops # 创建一些文件&lt;/p&gt;

&lt;p&gt;bin/rails destroy model Oops # 删除上面所创建的文件&lt;/p&gt;
&lt;h4 id="bin/rails"&gt;bin/rails&lt;/h4&gt;
&lt;p&gt;可以使用 bin/rails --help 来获取更详细的帮助指南&lt;/p&gt;

&lt;p&gt;还可以使用 bin/rails -T 来获取所有的任务列表&lt;/p&gt;
&lt;h4 id="bin/rails about"&gt;bin/rails about&lt;/h4&gt;
&lt;p&gt;它可以用来获取 Rails、Ruby、RubyGems、Rack、JavaScript Runtime 的版本号。rails 子组件，应用程序文件夹，当前 rails 的环境变量以及你所使用的数据库&lt;/p&gt;
&lt;h4 id="资源"&gt;资源&lt;/h4&gt;
&lt;p&gt;在 app/assets 目录中可以使用 bin/rails assets:precompile 预编译你的资源。如果你想移除资源使用 bin/rails assets:clean. &lt;/p&gt;

&lt;p&gt;如果你想完全清除 public/assets 资源，可以使用 bin/rails assets:clobber&lt;/p&gt;
&lt;h4 id="路由"&gt;路由&lt;/h4&gt;
&lt;p&gt;bin/rails routes 命令可以列出你目前所有的路由信息&lt;/p&gt;
&lt;h4 id="代码信息统计"&gt;代码信息统计&lt;/h4&gt;
&lt;p&gt;rails stats 可以对你的代码做统计&lt;/p&gt;

&lt;p&gt;感谢阅读 &lt;img title=":grinning:" alt="😀" src="https://twemoji.ruby-china.com/2/svg/1f600.svg" class="twemoji"&gt; &lt;/p&gt;</description>
      <author>monsterooo</author>
      <pubDate>Mon, 16 Jul 2018 03:22:49 +0800</pubDate>
      <link>https://ruby-china.org/topics/37162</link>
      <guid>https://ruby-china.org/topics/37162</guid>
    </item>
    <item>
      <title>请问一下"老鸟"们一个权限问题</title>
      <description>&lt;pre class="highlight shell"&gt;&lt;code&gt;➜  sample_app git:&lt;span class="o"&gt;(&lt;/span&gt;master&lt;span class="o"&gt;)&lt;/span&gt; ✗ gem &lt;span class="nb"&gt;install &lt;/span&gt;bootstrap-sass
Fetching: autoprefixer-rails-8.6.5.gem &lt;span class="o"&gt;(&lt;/span&gt;100%&lt;span class="o"&gt;)&lt;/span&gt;
ERROR:  While executing gem ... &lt;span class="o"&gt;(&lt;/span&gt;Gem::FilePermissionError&lt;span class="o"&gt;)&lt;/span&gt;
    You don&lt;span class="s1"&gt;'t have write permissions for the /Library/Ruby/Gems/2.3.0 directory.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;为什么用 gem 安装都要加上&lt;code&gt;sudo&lt;/code&gt;权限呢~&lt;/p&gt;</description>
      <author>monsterooo</author>
      <pubDate>Sat, 14 Jul 2018 16:07:52 +0800</pubDate>
      <link>https://ruby-china.org/topics/37157</link>
      <guid>https://ruby-china.org/topics/37157</guid>
    </item>
  </channel>
</rss>
