<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>kxu1988 (kxu1988)</title>
    <link>https://ruby-china.org/kxu1988</link>
    <description>kxu@ec2star.com</description>
    <language>en-us</language>
    <item>
      <title>[上海/北京] [初创企业] Foxu.ai（蜂略）招聘一名 Rails/Python 后端工程师 12-18K</title>
      <description>&lt;p&gt;【关于我们】&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;蜂略（上海）科技有限公司致力于将管理智慧与 AI 技术深度融合，打造 AIP（AI-Powered）智能平台，为中国制造业企业提供全方位的出海服务解决方案。&lt;/li&gt;
&lt;li&gt;&lt;p&gt;我们的使命是助力中国制造业企业成功出海并实现全球化发展，愿景是成为全球领先的 AI 驱动的 B2B 企业增长合作伙伴。我们为缺乏成熟国际市场团队、经验或资源的中国制造业企业，提供一个高性价比、结果导向、快速启动的“第二 AI 市场部”，实现可衡量的全球业务增长。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;业务介绍：b2b.foxlen.com&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;p&gt;【职位描述：Rails/Python 工程师】&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;我们正在寻找一名有 1-3 年 Rails 或 Python 开发经验的工程师，负责后端开发。考虑到我们 AI 团队的技术栈主要使用 Python，如果您同时掌握 Python，那将是极大的加分项！&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;任职要求：&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;年Ruby&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="no"&gt;Rails或Python&lt;/span&gt;&lt;span class="err"&gt;（&lt;/span&gt;&lt;span class="no"&gt;Django&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="no"&gt;Flask等&lt;/span&gt;&lt;span class="err"&gt;）&lt;/span&gt;&lt;span class="n"&gt;项目开发经验&lt;/span&gt;&lt;span class="err"&gt;。&lt;/span&gt;
&lt;span class="n"&gt;熟悉所用框架的常用功能和最佳实践&lt;/span&gt;&lt;span class="err"&gt;。&lt;/span&gt;
&lt;span class="n"&gt;熟悉关系型数据库&lt;/span&gt;&lt;span class="err"&gt;（&lt;/span&gt;&lt;span class="n"&gt;如PostgreSQL&lt;/span&gt;&lt;span class="err"&gt;）&lt;/span&gt;&lt;span class="n"&gt;的设计和优化&lt;/span&gt;&lt;span class="err"&gt;。&lt;/span&gt;
&lt;span class="n"&gt;了解或具备API设计和开发经验&lt;/span&gt;&lt;span class="err"&gt;（&lt;/span&gt;&lt;span class="no"&gt;RESTful&lt;/span&gt; &lt;span class="no"&gt;API&lt;/span&gt;&lt;span class="err"&gt;）。&lt;/span&gt;
&lt;span class="n"&gt;熟悉Git版本控制工具&lt;/span&gt;&lt;span class="err"&gt;。&lt;/span&gt;
&lt;span class="n"&gt;具备良好的编码规范和测试习惯&lt;/span&gt;&lt;span class="err"&gt;。&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;上海工作地点：上海市普陀区长风中心三期&lt;/li&gt;
&lt;li&gt;&lt;p&gt;北京工作地点：北京市海淀区中钢国际广场&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;薪资待遇：12K - 18K/月&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;联系邮箱：hr@foxlen.com&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <author>kxu1988</author>
      <pubDate>Thu, 03 Jul 2025 09:08:28 +0800</pubDate>
      <link>https://ruby-china.org/topics/44210</link>
      <guid>https://ruby-china.org/topics/44210</guid>
    </item>
    <item>
      <title>讨论一下 Cursor AI 和 Rails8.0？</title>
      <description>&lt;p&gt;想尝试使用 Cursor AI 和 Rails8.0 开发公司的新项目，希望社区里有人可以介绍经验。
在 youtube 上关注了一个账号“AI on Rails”，学习后也会把自己的一些心得发出来交流
&lt;img src="https://l.ruby-china.com/photo/kxu1988/2d5b7f0c-628e-4e14-b0ea-60e99832c140.png!large" title="" alt=""&gt;&lt;/p&gt;</description>
      <author>kxu1988</author>
      <pubDate>Tue, 18 Mar 2025 11:07:59 +0800</pubDate>
      <link>https://ruby-china.org/topics/44098</link>
      <guid>https://ruby-china.org/topics/44098</guid>
    </item>
    <item>
      <title>Tesla backend is in Rails</title>
      <description>&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/kxu1988/1598edae-57c3-4365-a577-ddb53c365993.jpg!large" title="" alt=""&gt;
&lt;img src="https://l.ruby-china.com/photo/kxu1988/3f9feff8-5165-461d-b755-49d7a088cf5c.jpg!large" title="" alt=""&gt;&lt;/p&gt;</description>
      <author>kxu1988</author>
      <pubDate>Thu, 10 Mar 2022 18:29:05 +0800</pubDate>
      <link>https://ruby-china.org/topics/42199</link>
      <guid>https://ruby-china.org/topics/42199</guid>
    </item>
    <item>
      <title>Rails 6 版本采用 Webpacker 时 JS 的写法</title>
      <description>&lt;p&gt;Rails 版本是 6.1.3，然后参考官方文档&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="ss"&gt;javascript:
  &lt;/span&gt;&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="ss"&gt;packs:
  &lt;/span&gt;&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="c1"&gt;# only webpack entry files here&lt;/span&gt;
  &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;js&lt;/span&gt;
  &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;css&lt;/span&gt;
  &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="ss"&gt;src:
  &lt;/span&gt;&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;my_component&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;js&lt;/span&gt;
  &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="ss"&gt;stylesheets:
  &lt;/span&gt;&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;my_styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;css&lt;/span&gt;
  &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="ss"&gt;images:
      &lt;/span&gt;&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;logo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;svg&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我在 app/javascript 下面新建了 src 文件夹，把 init-alpine.js 文件放入：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="ss"&gt;javascript:
  &lt;/span&gt;&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="ss"&gt;channels:
  &lt;/span&gt;&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="ss"&gt;controllers:
  &lt;/span&gt;&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="ss"&gt;packs:
  &lt;/span&gt;&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;js&lt;/span&gt;
  &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="ss"&gt;src:
  &lt;/span&gt;&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;alpine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;js&lt;/span&gt;
  &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="ss"&gt;stylesheets:
      &lt;/span&gt;&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scss&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;init-alpine.js 代码如下&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getThemeFromLocalStorage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// if user already changed the theme, use it&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&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="c1"&gt;// else return their preferences&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matchMedia&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
      &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;matchMedia&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;(prefers-color-scheme: dark)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;setThemeToLocalStorage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&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="na"&gt;dark&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;getThemeFromLocalStorage&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nf"&gt;toggleTheme&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&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;dark&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&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;dark&lt;/span&gt;
      &lt;span class="nf"&gt;setThemeToLocalStorage&lt;/span&gt;&lt;span class="p"&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;dark&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;isSideMenuOpen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;toggleSideMenu&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&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;isSideMenuOpen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&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;isSideMenuOpen&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;在 packs/application.js 里 import {data} from "../src/init-alpine.js"运行项目之后，是可以看到前端加载了 init-alpine.js 的，但是控制台报错找不到 data()。&lt;/p&gt;

&lt;p&gt;然后找了一下在“../src/init-alpine.js“增加了 export，第一行代码修改为了”export funtion data()“,仍然是同样的问题，只能把 init-alpine.js 的代码放入 erb 网页里才起作用。&lt;/p&gt;

&lt;p&gt;最后在 GitHub 上搜索了一些 rails6 template 类型的项目，找到了一个这样的写法：
&lt;img src="https://l.ruby-china.com/photo/kxu1988/f9f761bc-21b6-490f-8832-27b73633e9f4.png!large" title="" alt=""&gt;
这里是项目地址：&lt;a href="https://github.com/Vic-L/rails6boilerplate/tree/master/app/javascript/packs" rel="nofollow" target="_blank"&gt;https://github.com/Vic-L/rails6boilerplate/tree/master/app/javascript/packs&lt;/a&gt;
他的方式是把所有 js 都放入 packs 文件夹下面，然后自己的 js 代码直接放入 packs 文件夹下面的 js 文件里，并不单独管理自己的 js 代码，然后在 packs 下去 require 或 import，下面截取了其中 application.js 的一段代码：&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@rails/ujs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;turbolinks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@rails/activestorage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;channels&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jquery&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;chart.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bootstrap&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jquery.easing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;animate.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;owl.carousel/dist/assets/owl.carousel.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;owl.carousel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jquery-hoverintent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;wowjs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;superfish&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;venobox&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;venobox/venobox/venobox.min.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// custom&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../scss/web/web.scss&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../scss/fontawesome.scss&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../scss/fields.sass&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// images&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../images&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;imagePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;images&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;WOW&lt;/span&gt; &lt;span class="p"&gt;}&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;wowjs&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;togglePasswordField&lt;/span&gt; &lt;span class="p"&gt;}&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;./password.js&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;autocapitalize&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;./autocapitalize.js&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="s2"&gt;turbolinks:load&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="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scrollTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;togglePasswordField&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;autocapitalize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Back to top button&lt;/span&gt;
  &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;scroll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;scrollTop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.back-to-top&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fadeIn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;slow&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="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.back-to-top&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fadeOut&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;slow&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;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.back-to-top&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;html, body&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;scrollTop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;easeInOutExpo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Header fixed on scroll&lt;/span&gt;
  &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;scroll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;scrollTop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#header&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;addClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;header-scrolled&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="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#header&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;removeClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;header-scrolled&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;因为在 GitHub 上只找到了这一个实践参考，感觉也不是很好的方式，所以想请大家指教一下更好的实践方式&lt;/p&gt;</description>
      <author>kxu1988</author>
      <pubDate>Thu, 01 Apr 2021 09:36:07 +0800</pubDate>
      <link>https://ruby-china.org/topics/41097</link>
      <guid>https://ruby-china.org/topics/41097</guid>
    </item>
    <item>
      <title>[北京中关村] 兰谷文化 长期招聘 Ruby 工程师 ( 20K - 35K )</title>
      <description>&lt;p&gt;我们是一家初创艺术品电商，我们致力于解决传统艺术品在线下交易周期长、成交难、信息不对成等弊端，让艺术品在不断的流通和交换中产生价值。&lt;br&gt;
公司地址：北京市海淀区中关村中国电子大厦（10 号线海淀黄庄站）  &lt;/p&gt;

&lt;p&gt;邮箱：kxu@ec2star.com&lt;br&gt;
微信：purenumber&lt;br&gt;
欢迎随时联系我，我会尽快回复  &lt;/p&gt;
&lt;h2 id="Ruby 开发工程师（电商方向，2 名）"&gt;Ruby 开发工程师（电商方向，2 名）&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;  薪资范围：20k-35k&lt;/li&gt;
&lt;li&gt;  上下班时间 9:30-18:30/适当弹性上下班；&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="工作职责："&gt;工作职责：&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt; 负责电商平台（官网、商城系统、订单系统、支付中心、营销平台等）各业务系统的研发和维护&lt;/li&gt;
&lt;li&gt; 定期技术分享及为团队成员进行 Code Review&lt;/li&gt;
&lt;li&gt; 负责公司其它产品业务线开发&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="任职要求："&gt;任职要求：&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt; 2 年以上 Ruby on Rails 开发经验&lt;/li&gt;
&lt;li&gt; 精通数据库的开发、配置、维护，了解性能优化&lt;/li&gt;
&lt;li&gt; 熟悉 HTML、CSS、JavaScript，能独立开发上线完整应用&lt;/li&gt;
&lt;li&gt; 有编写自动化测试习惯，熟悉 CI/CD 流程，编码习惯良好&lt;/li&gt;
&lt;li&gt; 了解 Web 应用常见漏洞，了解静态漏洞扫描工具，安全意识高&lt;/li&gt;
&lt;li&gt; 曾经作为主要开发者参与商业项目，能快速理解业务需求并转化为输出&lt;/li&gt;
&lt;li&gt; 了解前端工具链 Node.js、npm/Yarn、Webpack 者优先&lt;/li&gt;
&lt;li&gt; 熟悉容器化相关技术，掌握 Docker、K8S 的使用者优先&lt;/li&gt;
&lt;li&gt; 有主导开源项目经验，例如提交 PR、Issue，翻译文档者优先&lt;/li&gt;
&lt;li&gt;具备大型电子商务网站核心系统开发、设计工作经验者优先&lt;/li&gt;
&lt;/ol&gt;</description>
      <author>kxu1988</author>
      <pubDate>Mon, 21 Oct 2019 21:43:46 +0800</pubDate>
      <link>https://ruby-china.org/topics/39174</link>
      <guid>https://ruby-china.org/topics/39174</guid>
    </item>
    <item>
      <title>base64encode 的值通过 md5 不一致的问题</title>
      <description>&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generateSignature&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="nb"&gt;hash&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;OpenSSL&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HMAC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'sha256'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"as2das231d12asdsada1212a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="no"&gt;Base64&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode64&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="c1"&gt;#result.gsub!("\n", '')&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"========result:&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="n"&gt;signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Digest&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;MD5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hexdigest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"========signature====&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;signature&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;ul&gt;
&lt;li&gt;打印的 result 值为“gmBQdw9tdiWDFCUUshLNYdrHIRHyeTN8kPNWipUBbd8=”&lt;/li&gt;
&lt;li&gt;打印的结果 signature 是"32b529663f5a8cca9969cf89f0775a46"&lt;/li&gt;
&lt;li&gt;使用 md5 在线加密 result(&lt;a href="https://md5jiami.51240.com" rel="nofollow" target="_blank"&gt;https://md5jiami.51240.com&lt;/a&gt;), 结果是:43708b7e323e32f36b0ba609757b5e30&lt;/li&gt;
&lt;li&gt;此时两个结果不一致&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;ul&gt;
&lt;li&gt;当我把代码里 signature = Digest::MD5.hexdigest(result) 里的 result 换成：&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Digest&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;MD5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hexdigest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;gmBQdw9tdiWDFCUUshLNYdrHIRHyeTN8kPNWipUBbd8&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;- 此时，打印的 signature 跟 md5 在线加密（&lt;a href="https://md5jiami.51240.com" rel="nofollow" target="_blank"&gt;https://md5jiami.51240.com&lt;/a&gt;）的结果一致&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;请问我哪里出了问题？&lt;/li&gt;
&lt;/ul&gt;</description>
      <author>kxu1988</author>
      <pubDate>Wed, 03 Apr 2019 19:03:45 +0800</pubDate>
      <link>https://ruby-china.org/topics/38341</link>
      <guid>https://ruby-china.org/topics/38341</guid>
    </item>
    <item>
      <title>关于数据权限控制</title>
      <description>&lt;p&gt;需求：
系统有多个组织机构，每个机构只能看到当前机构的数据&lt;/p&gt;

&lt;p&gt;问题：
1.数据权限控制有类似 cancan 的 gem 可以参考吗？
2.数据权限控制一般有哪些处理的方法？&lt;/p&gt;

&lt;p&gt;我的想法：
业务数据存储相关的表都有 organization_id 字段;
在执行所有 sql 查询操作的时候检查该表是否存在 organization_id 字段，如果存在，给该 sql 增加一个查询条件&lt;/p&gt;</description>
      <author>kxu1988</author>
      <pubDate>Thu, 07 Mar 2019 08:31:25 +0800</pubDate>
      <link>https://ruby-china.org/topics/38203</link>
      <guid>https://ruby-china.org/topics/38203</guid>
    </item>
    <item>
      <title>Action Cable + Nginx 生产环境配置</title>
      <description>&lt;h2 id="项目背景"&gt;项目背景&lt;/h2&gt;
&lt;p&gt;最近把公司产品升级到了 Rails5.2，Rails 主要用来提供 API 服务，以及后台数据管理；&lt;br&gt;
同时，Rails 跟 Android APP 之间有部分功能需要用到 WebSocket 通信，&lt;br&gt;
WebSocket 方面采用了 Rails5 的 Action Cable。  &lt;/p&gt;

&lt;p&gt;在生产环境发布项目时候遇到了诸多问题，官网的文档以及网络上的资料都介绍的不是很强，这里把自己的配置过程分享给大家，有遇到同样需求的朋友可以参考。&lt;/p&gt;
&lt;h2 id="Nginx配置"&gt;Nginx 配置&lt;/h2&gt;
&lt;p&gt;Nginx 版本使用的最新的稳定版：1.14.0&lt;br&gt;
看官网文档介绍，自从 1.3.13 版本之后，Nginx 实现了一种特殊的运行模式：  &lt;/p&gt;

&lt;p&gt;&lt;a href="http://nginx.org/en/docs/http/websocket.html" rel="nofollow" target="_blank"&gt;http://nginx.org/en/docs/http/websocket.html&lt;/a&gt;  &lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;since version 1.3.13, 
nginx implements special mode of operation that allows setting up a tunnel between a client and proxied server
&lt;span class="k"&gt;if &lt;/span&gt;the proxied server returned a response with the code 101 &lt;span class="o"&gt;(&lt;/span&gt;Switching Protocols&lt;span class="o"&gt;)&lt;/span&gt;, 
and the client asked &lt;span class="k"&gt;for &lt;/span&gt;a protocol switch via the “Upgrade” header &lt;span class="k"&gt;in &lt;/span&gt;a request.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;所以 proxied server 会把头部带有“Upgrade”和“Connection”的转为 Websocket 协议，Nginx 配置文件例子如下：&lt;/p&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="n"&gt;upstream&lt;/span&gt; &lt;span class="n"&gt;deploy&lt;/span&gt; {
         &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="n"&gt;unix&lt;/span&gt;:///&lt;span class="n"&gt;var&lt;/span&gt;/&lt;span class="n"&gt;www&lt;/span&gt;/&lt;span class="n"&gt;api&lt;/span&gt;.&lt;span class="n"&gt;yoursite&lt;/span&gt;.&lt;span class="n"&gt;com&lt;/span&gt;/&lt;span class="n"&gt;shared&lt;/span&gt;/&lt;span class="n"&gt;tmp&lt;/span&gt;/&lt;span class="n"&gt;sockets&lt;/span&gt;/&lt;span class="n"&gt;puma&lt;/span&gt;.&lt;span class="n"&gt;sock&lt;/span&gt;;
 }

&lt;span class="n"&gt;location&lt;/span&gt; /&lt;span class="n"&gt;chat&lt;/span&gt; {      &lt;span class="c"&gt;#注意，在Rails里有相应的配置
&lt;/span&gt;    &lt;span class="n"&gt;proxy_pass&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;://&lt;span class="n"&gt;deploy&lt;/span&gt;;  &lt;span class="c"&gt;#这里对应着我上面的Server
&lt;/span&gt;    &lt;span class="n"&gt;proxy_http_version&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;.&lt;span class="m"&gt;1&lt;/span&gt;;
    &lt;span class="n"&gt;proxy_set_header&lt;/span&gt; &lt;span class="n"&gt;Upgrade&lt;/span&gt; $&lt;span class="n"&gt;http_upgrade&lt;/span&gt;;
    &lt;span class="n"&gt;proxy_set_header&lt;/span&gt; &lt;span class="n"&gt;Connection&lt;/span&gt; &lt;span class="s2"&gt;"upgrade"&lt;/span&gt;;
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="Rails配置"&gt;Rails 配置&lt;/h2&gt;
&lt;p&gt;在 config/environments/production.rb 里面加入如下两句话  &lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;action_cable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'/chat'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;   
&lt;span class="c1"&gt;#这里开始我没有加，nginx日志里一直报找不到网址，后来在Rails的日志里发现这个问题&lt;/span&gt;
 &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;action_cable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;disable_request_forgery_protection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;</description>
      <author>kxu1988</author>
      <pubDate>Sun, 20 May 2018 17:54:09 +0800</pubDate>
      <link>https://ruby-china.org/topics/36807</link>
      <guid>https://ruby-china.org/topics/36807</guid>
    </item>
    <item>
      <title>[北京] 北京清软时代科技有限公司招聘 Rails 程序员 3 名 </title>
      <description>&lt;p&gt;Ruby 开发工程师 2 名
招聘要求：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;1 年以上 Ruby on Rails 开发经验；&lt;/li&gt;
&lt;li&gt;扎实的 Ruby 语言基础，良好的编程习惯；&lt;/li&gt;
&lt;li&gt;熟悉 Linux、MySQL&lt;/li&gt;
&lt;li&gt;熟悉 HTML、CSS、JavaScript&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;薪资待遇：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;月薪 8k-12k&lt;/li&gt;
&lt;li&gt;年终 1-3 个月将近&lt;/li&gt;
&lt;li&gt;五险一金&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ruby 实习生 1 名
招聘要求：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;有较好的编程基础，熟悉任何一门开发语言&lt;/li&gt;
&lt;li&gt;热爱 Ruby on Rails&lt;/li&gt;
&lt;li&gt;喜欢研究新技术&lt;/li&gt;
&lt;li&gt;英语阅读能力突出&lt;/li&gt;
&lt;li&gt;了解 HTML、CSS、JavaScript 的优先&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;薪资待遇：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;每天 200，每周可以实习的时间不少于 4 天，且可长期实习；&lt;/li&gt;
&lt;li&gt;每天 20 饭补&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;有意者请发送简历至 kxu@14cells.com&lt;/p&gt;</description>
      <author>kxu1988</author>
      <pubDate>Thu, 05 Jun 2014 09:27:02 +0800</pubDate>
      <link>https://ruby-china.org/topics/19750</link>
      <guid>https://ruby-china.org/topics/19750</guid>
    </item>
  </channel>
</rss>
