<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Ian (Ian)</title>
    <link>https://ruby-china.org/Ian</link>
    <description></description>
    <language>en-us</language>
    <item>
      <title>尊嘟网络科技（深圳）有限公司招聘初/中级 Ruby On Rails 全栈工程师 15k ~ 20k</title>
      <description>&lt;h2 id="公司概述"&gt;公司概述&lt;/h2&gt;
&lt;p&gt;FRL (&lt;a href="https://getfrl.com" rel="nofollow" target="_blank"&gt;https://getfrl.com&lt;/a&gt;) 是一家创新型社交电商科技初创公司，专注于欧美市场的社交电商业务，团队创始人都是资深的欧美电商行业从业者。 &lt;/p&gt;
&lt;h2 id="职位概述："&gt;职位概述：&lt;/h2&gt;
&lt;p&gt;我们在寻求一位具有经验的初/中级 Ruby on Rails 开发工程师来加强我们的团队。作为团队中的一员，你将参与到项目的各个阶段，负责开发可扩展且稳定的网络应用程序。你也将与团队成员紧密协作，共同促进我们产品的进步和优化。&lt;/p&gt;
&lt;h2 id="职位名称："&gt;职位名称：&lt;/h2&gt;
&lt;p&gt;Ruby On Rails 全栈开发工程师（Hotwire 技术栈）&lt;/p&gt;
&lt;h2 id="工作地点："&gt;工作地点：&lt;/h2&gt;
&lt;p&gt;深圳 · 南山前海&lt;/p&gt;
&lt;h2 id="职责和要求："&gt;职责和要求：&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;负责 FRL 平台的设计、开发和维护。&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;h2 id="职位要求："&gt;职位要求：&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;有 2 年以上的 Ruby on Rails 开发经验。&lt;/li&gt;
&lt;li&gt;熟练掌握 Ruby 语言和 Rails 框架。&lt;/li&gt;
&lt;li&gt;熟悉 Hotwire 框架 ( Turbo / StimulusJS )。&lt;/li&gt;
&lt;li&gt;熟悉 HTML5 + CSS3 , 熟练使用 TailwindCSS。&lt;/li&gt;
&lt;li&gt;熟悉常用的数据库系统，如 PostgreSQL、MySQL 等。&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;h2 id="加分项："&gt;加分项：&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;可做工作语言的英文口语能力。&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;h2 id="福利待遇:"&gt;福利待遇：&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;薪资范围 15k - 20k。&lt;/li&gt;
&lt;li&gt;工资包括基本工资+bonus+Stock Option，具体情况要根据个人背景和能力来定。&lt;/li&gt;
&lt;li&gt;弹性工作时间，充分体现工作与生活的平衡。&lt;/li&gt;
&lt;li&gt;我们反对 996，主张在工作时间内完成工作任务。&lt;/li&gt;
&lt;li&gt;地铁直达办公室。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="联系方式："&gt;联系方式：&lt;/h2&gt;
&lt;p&gt;欢迎发送简历到 jobs@get.frl，我们会尽快和你取得联系。&lt;/p&gt;</description>
      <author>Ian</author>
      <pubDate>Mon, 21 Oct 2024 14:15:04 +0800</pubDate>
      <link>https://ruby-china.org/topics/43923</link>
      <guid>https://ruby-china.org/topics/43923</guid>
    </item>
    <item>
      <title>推荐一个让页面支持 live reload 的 Gem —— rails_live_reload</title>
      <description>&lt;p&gt;&lt;a href="https://github.com/railsjazz/rails_live_reload" rel="nofollow" target="_blank" title=""&gt;rails_live_reload&lt;/a&gt; 是一个让页面可以热重载的 Gem，页面/CSS/JS 修改后会自动刷新浏览器页面。类似的 Gem 还有 &lt;a href="https://github.com/guard/guard-livereload" rel="nofollow" target="_blank" title=""&gt;guard-livereload&lt;/a&gt; ，还有 &lt;a href="https://github.com/kirillplatonov/hotwire-livereload" rel="nofollow" target="_blank" title=""&gt;hotwire-livereload&lt;/a&gt;。不过 guard-livereload 依赖于 Guard，hotwire-livereload 依赖于 Redis，所以我选择了 rails_live_reload。&lt;/p&gt;</description>
      <author>Ian</author>
      <pubDate>Sun, 28 Apr 2024 19:05:38 +0800</pubDate>
      <link>https://ruby-china.org/topics/43669</link>
      <guid>https://ruby-china.org/topics/43669</guid>
    </item>
    <item>
      <title>在 Ruby On Rails 中使用 helper 实现 slot 功能</title>
      <description>&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/Ian/08a7a88b-a801-4c16-aed0-bb3472ee0628.png!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Image: &lt;a href="https://unsplash.com/photos/oUTugmSkagk" rel="nofollow" target="_blank"&gt;https://unsplash.com/photos/oUTugmSkagk&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;原文： &lt;a href="https://mini-geek.com/posts/77" rel="nofollow" target="_blank"&gt;https://mini-geek.com/posts/77&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="什么是 Slot ？"&gt;什么是 Slot？&lt;/h2&gt;
&lt;p&gt;我们这里说到的 slot 是 view 层面的，通常用于组件中。slot 的意思是插槽，同字面上的意思，它们是一些占位符，我们可以在调用到时才决定传递什么样的结构进去，这使得我们可以更加灵活的复用组件。&lt;/p&gt;
&lt;h2 id="Slot 用于解决什么样的问题？"&gt;Slot 用于解决什么样的问题？&lt;/h2&gt;
&lt;p&gt;举个例子，我们的 web 应用中通常都会使用到 Modal（模态框）这个组件，通常 Modal 都是结构都是固定的。下面是 Bootstrap 中一个 Modal 使用的例子：&lt;/p&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"exampleModal"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"modal"&lt;/span&gt; &lt;span class="na"&gt;tabindex=&lt;/span&gt;&lt;span class="s"&gt;"-1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- 1. id --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"modal-dialog"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"modal-content"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"modal-header"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h5&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"modal-title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Modal title&lt;span class="nt"&gt;&amp;lt;/h5&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- 2. 标题 --&amp;gt;&lt;/span&gt; 
        &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn-close"&lt;/span&gt; &lt;span class="na"&gt;data-bs-dismiss=&lt;/span&gt;&lt;span class="s"&gt;"modal"&lt;/span&gt; &lt;span class="na"&gt;aria-label=&lt;/span&gt;&lt;span class="s"&gt;"Close"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"modal-body"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Modal body text goes here.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- 3. 模态框主体 --&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"modal-footer"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
        &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn btn-secondary"&lt;/span&gt; &lt;span class="na"&gt;data-bs-dismiss=&lt;/span&gt;&lt;span class="s"&gt;"modal"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Close&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- 4. 模态框的操作按钮 --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn btn-primary"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Save changes&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;上面标出来的 4 个部分：id，标题，主体，操作按钮，通常是一个模态框会变动的地方（样式也可能会变，不过样式变化的问题比较容易解决，这里先忽略）。如果在每一个用到模态框的位置都写上这么一大串代码，显然是会影响代码的可读性和可维护性的。这个时候就可以用上我们之前说到的插槽的概念了。&lt;/p&gt;

&lt;p&gt;接下来我们以 Modal 为例子，介绍一下如何使用 Rails 的 helper + partial + 一个简单的对象，来将这类代码封装成通用的组件。（&lt;a href="https://github.com/ViewComponent/view_component" rel="nofollow" target="_blank" title=""&gt;ViewComponent&lt;/a&gt; 这个 Gem 也提供了 slot 的功能，这里我们介绍如何使用 Rails 原生的方式来实现）&lt;/p&gt;
&lt;h2 id="实现"&gt;实现&lt;/h2&gt;
&lt;p&gt;首先我们要初始化一个项目：&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;rails new demo &lt;span class="nt"&gt;-c&lt;/span&gt; bootstrap
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;初始化完成之后，我们先生成一个控制器用于演示：&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;demo
&lt;span class="nv"&gt;$ &lt;/span&gt;rails generate controller home show
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这里我们生成了一个只有 show action 的控制器 HomeController，并且生成了对应的页面：&lt;/p&gt;

&lt;p&gt;新建 &lt;code&gt;app/helpers/component_context.rb&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;ComponentContext&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;BasicObject&lt;/span&gt;  
  &lt;span class="nb"&gt;attr_accessor&lt;/span&gt; &lt;span class="ss"&gt;:slots&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;view_context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="vi"&gt;@view_context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;view_context&lt;/span&gt;  
    &lt;span class="vi"&gt;@slots&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;  
  &lt;span class="k"&gt;end&lt;/span&gt;  

  &lt;span class="kp"&gt;private&lt;/span&gt;  

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;method_missing&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="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
      &lt;span class="vi"&gt;@slots&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="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@view_context.capture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="k"&gt;end&lt;/span&gt;  
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ComponentContext 是实现 slot 功能的关键。这里简单介绍下 ComponentContext 的作用，这个类首先定义了一个 slots 的 accessor，这里是为了后面我们能保存以及获取到 slot 里边的内容。然后定义了一个 initialize 方法，接收一个 &lt;a href="https://api.rubyonrails.org/v7.1.2/classes/ActionView/Rendering.html#method-i-view_context" rel="nofollow" target="_blank" title=""&gt;view_context&lt;/a&gt; 参数，这个 view_context 可以在 view 或 helper 中直接调用 self 获取到，默认是 ActionView::Base 的实例。接下来定义了 method_missing 方法，这个方法会在对象找不到方法时被调用。里边用到了 helper 里边的 &lt;a href="https://api.rubyonrails.org/classes/ActionView/Helpers/CaptureHelper.html" rel="nofollow" target="_blank" title=""&gt;capture 方法&lt;/a&gt;，这个方法可以捕捉 block 里边的内容并返回，这里我们用它接受 slot 的传值，这意味着调用 ComponentContext 中任意不存在的方法时，实际上都会往 &lt;a href="/slots" class="user-mention" title="@slots"&gt;&lt;i&gt;@&lt;/i&gt;slots&lt;/a&gt; 里边存传入的 block 里边的内容，键就是调用时的方法名，同时也是相应 slot 的名字。使用 method_missing 是为了能让这个 ComponentContext 可以被所有的组件复用，它可以接受任意的 slot。同时，因为这个类只用于保存 slot 的值，所以使用 method_missing 的副作用也就没那么大了。&lt;/p&gt;

&lt;p&gt;新建 &lt;code&gt;app/helpers/components_helper.rb&lt;/code&gt; ，内容如下：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;ComponentsHelper&lt;/span&gt;

  &lt;span class="c1"&gt;# Usage:&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;# &amp;lt;%= modal id: "modalExample", title: "A simple modal example" do |m| %&amp;gt;&lt;/span&gt;
  &lt;span class="c1"&gt;#   &amp;lt;% m.with_body do %&amp;gt;&lt;/span&gt;
  &lt;span class="c1"&gt;#     &amp;lt;span&amp;gt;Modal content&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="c1"&gt;#   &amp;lt;% end %&amp;gt;&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;#   &amp;lt;% m.with_footer do %&amp;gt;&lt;/span&gt;
  &lt;span class="c1"&gt;#     &amp;lt;button type="button" class="btn btn-primary"&amp;gt;OK&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="c1"&gt;#     &amp;lt;button type="button" class="btn btn-secondary" data-bs-dismiss="modal"&amp;gt;Close&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="c1"&gt;#   &amp;lt;% end %&amp;gt;&lt;/span&gt;
  &lt;span class="c1"&gt;# &amp;lt;% end %&amp;gt;&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;modal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:,&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:)&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;component_context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ComponentContext&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="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="s2"&gt;"components/modal"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:,&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;component_context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slots&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;我们可以把需要的组件都放在这个 helper 里边，不过你也可以根据自己的需求决定 helper 方法的位置，毕竟 Rails 中的 helper 是没有命名空间这个概念的。&lt;/p&gt;

&lt;p&gt;新建 app/views/components 文件夹&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;app/views/components
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;新建 &lt;code&gt;app/views/components/_modal.html.erb&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="na"&gt;#&lt;/span&gt; &lt;span class="na"&gt;locals:&lt;/span&gt; &lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="na"&gt;id:&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;title:&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;with_body:&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;with_footer:&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;%= id %&amp;gt;"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"modal fade"&lt;/span&gt; &lt;span class="na"&gt;tabindex=&lt;/span&gt;&lt;span class="s"&gt;"-1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- 1. id --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"modal-dialog"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"modal-content"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"modal-header"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h5&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"modal-title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/h5&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- 2. title --&amp;gt;&lt;/span&gt; 
        &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn-close"&lt;/span&gt; &lt;span class="na"&gt;data-bs-dismiss=&lt;/span&gt;&lt;span class="s"&gt;"modal"&lt;/span&gt; &lt;span class="na"&gt;aria-label=&lt;/span&gt;&lt;span class="s"&gt;"Close"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"modal-body"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;with_body&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- 3. with_body --&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"modal-footer"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
        &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;with_footer&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- 4. with_footer --&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个就是我们的组件模板了，&lt;code&gt;id&lt;/code&gt; 和  &lt;code&gt;title&lt;/code&gt; 是常规的变量，而 &lt;code&gt;with_body&lt;/code&gt; 和 &lt;code&gt;with_footer&lt;/code&gt; 就是我们的 slot 了，我们在给 slot 传值的时候也要使用相同的名字。&lt;/p&gt;

&lt;p&gt;修改 &lt;code&gt;app/views/home/show.html.erb&lt;/code&gt; 的内容为：&lt;/p&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"p-5"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn btn-primary"&lt;/span&gt; &lt;span class="na"&gt;data-bs-toggle=&lt;/span&gt;&lt;span class="s"&gt;"modal"&lt;/span&gt; &lt;span class="na"&gt;data-bs-target=&lt;/span&gt;&lt;span class="s"&gt;"#exampleModal"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Launch demo modal
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;modal&lt;/span&gt; &lt;span class="na"&gt;id:&lt;/span&gt; &lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;exampleModal&lt;/span&gt;&lt;span class="err"&gt;",&lt;/span&gt; &lt;span class="na"&gt;title:&lt;/span&gt; &lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;Example&lt;/span&gt; &lt;span class="na"&gt;modal&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt; &lt;span class="na"&gt;do&lt;/span&gt; &lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="na"&gt;m&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;m.with_body&lt;/span&gt; &lt;span class="na"&gt;do&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- 这里我们给 with_body 这个 slot 传值 --&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt;Modal content&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;m.with_footer&lt;/span&gt; &lt;span class="na"&gt;do&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- 这里我们给 with_footer 这个 slot 传值 --&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn btn-primary"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;OK&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn btn-secondary"&lt;/span&gt; &lt;span class="na"&gt;data-bs-dismiss=&lt;/span&gt;&lt;span class="s"&gt;"modal"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Close&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;启动服务：&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;bin/dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;打开浏览器，访问 &lt;a href="http://localhost:3000/home/show" rel="nofollow" target="_blank" title=""&gt;http://localhost:3000/home/show&lt;/a&gt; ，点击按钮，可以看到模态框按照我们预想中的呈现了&lt;/p&gt;
&lt;h2 id="总结"&gt;总结&lt;/h2&gt;
&lt;p&gt;在实现 slot 这个功能的过程中，我们使用了 Rails 里边的 helper 和 partial，并且定义了一个名为 ComponentContext 的类来作为 helper 和 partial 中间的桥梁，最终实现了我们期望的效果&lt;/p&gt;</description>
      <author>Ian</author>
      <pubDate>Wed, 06 Mar 2024 10:10:25 +0800</pubDate>
      <link>https://ruby-china.org/topics/43612</link>
      <guid>https://ruby-china.org/topics/43612</guid>
    </item>
    <item>
      <title>Turbo 8 beta 版放出来了</title>
      <description>&lt;p&gt;morph 功能的演示，感觉相当不错啊
&lt;span class="embed-responsive embed-responsive-16by9"&gt;&lt;iframe class="embed-responsive-item" src="//www.youtube.com/embed/hKKycPLN-sk" allowfullscreen=""&gt;&lt;/iframe&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <author>Ian</author>
      <pubDate>Mon, 27 Nov 2023 20:10:39 +0800</pubDate>
      <link>https://ruby-china.org/topics/43491</link>
      <guid>https://ruby-china.org/topics/43491</guid>
    </item>
    <item>
      <title>Strada 发布了～</title>
      <description>&lt;p&gt;详情：&lt;a href="https://strada.hotwired.dev" rel="nofollow" target="_blank"&gt;https://strada.hotwired.dev&lt;/a&gt;&lt;/p&gt;</description>
      <author>Ian</author>
      <pubDate>Thu, 21 Sep 2023 21:23:49 +0800</pubDate>
      <link>https://ruby-china.org/topics/43348</link>
      <guid>https://ruby-china.org/topics/43348</guid>
    </item>
    <item>
      <title>写了一个打印数据库表结构的 Gem</title>
      <description>&lt;p&gt;之前查看表结构的方式一直都是使用的 &lt;code&gt;annotate&lt;/code&gt; 这个 gem，但是将表结构作为注释嵌入在模型里感觉不是很好，而且字段多的时候看起来不太舒服。所以想着能不能在 console 里边打印表结构，然后就有了这个 gem: &lt;a href="https://github.com/otorain/table_inspector" rel="nofollow" target="_blank" title=""&gt;table_inspector&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;大概的用法是：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;TableInspector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scan&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;model_class&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输出结果类似：&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/Ian/33413b01-9508-4952-9b81-525315224d37.png!large" title="" alt="table_inspector_scan_table"&gt;&lt;/p&gt;

&lt;p&gt;更多用法写在 README 里边了： &lt;a href="https://github.com/otorain/table_inspector" rel="nofollow" target="_blank"&gt;https://github.com/otorain/table_inspector&lt;/a&gt;&lt;/p&gt;</description>
      <author>Ian</author>
      <pubDate>Mon, 20 Feb 2023 22:48:49 +0800</pubDate>
      <link>https://ruby-china.org/topics/42893</link>
      <guid>https://ruby-china.org/topics/42893</guid>
    </item>
    <item>
      <title>腾讯云的 k8s 集群 tke 开始收费了</title>
      <description>&lt;p&gt;之前看到腾讯云的集群托管 master 节点不收费，所以就买了个 worker 节点建了个，还打算拿来练练手，还没几天就开始要收费了，最低 0.13 元/小时&lt;/p&gt;

&lt;p&gt;这操作不是第一次了，去年内网负载均衡不收费改成 0.2 元/小时，公网负载均衡从 0.02 元/小时 涨到 0.2 元/小时&lt;/p&gt;

&lt;p&gt;真的是怕了，不过有一点腾讯云还是做的不错的，退费还是挺方便的。&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/Ian/0bc136ac-0c3a-4613-b921-621adc6db725.png!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/Ian/67b3a0b9-c8aa-488a-be82-ef80a718fed5.jpg!large" title="" alt=""&gt;&lt;/p&gt;</description>
      <author>Ian</author>
      <pubDate>Wed, 23 Feb 2022 19:32:24 +0800</pubDate>
      <link>https://ruby-china.org/topics/42158</link>
      <guid>https://ruby-china.org/topics/42158</guid>
    </item>
    <item>
      <title>社区的手机版页面好像没有找到搜索按钮</title>
      <description>&lt;p&gt;RT，想搜点啥的时候没找到...&lt;/p&gt;</description>
      <author>Ian</author>
      <pubDate>Thu, 17 Feb 2022 00:48:24 +0800</pubDate>
      <link>https://ruby-china.org/topics/42146</link>
      <guid>https://ruby-china.org/topics/42146</guid>
    </item>
    <item>
      <title>Ruby 3.1.0 Preview 1 Released</title>
      <description>&lt;ul&gt;
&lt;li&gt;YJIT merged，目前是实验性功能。默认禁用，使用 &lt;code&gt;--yjit&lt;/code&gt; 开启&lt;/li&gt;
&lt;li&gt;添加了语法糖&lt;code&gt;{x: x, y: y}&lt;/code&gt; 可写为 &lt;code&gt;{x: , y: }&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;One-line pattern matching，也就是像&lt;code&gt;{ a: 1, b: 2 } =&amp;gt; {a: , b: }&lt;/code&gt; 不再是 experimental 的了&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;其他的自己可以看看官网 &lt;a href="https://www.ruby-lang.org/en/news/2021/11/09/ruby-3-1-0-preview1-released" rel="nofollow" target="_blank"&gt;https://www.ruby-lang.org/en/news/2021/11/09/ruby-3-1-0-preview1-released&lt;/a&gt;&lt;/p&gt;</description>
      <author>Ian</author>
      <pubDate>Tue, 09 Nov 2021 23:43:46 +0800</pubDate>
      <link>https://ruby-china.org/topics/41866</link>
      <guid>https://ruby-china.org/topics/41866</guid>
    </item>
    <item>
      <title>大家对新发布的 mbp 有啥看法</title>
      <description>&lt;p&gt;感觉乔布斯的棺材板快压不住了 &lt;img title=":sweat_smile:" alt="😅" src="https://twemoji.ruby-china.com/2/svg/1f605.svg" class="twemoji"&gt; &lt;/p&gt;</description>
      <author>Ian</author>
      <pubDate>Tue, 19 Oct 2021 21:23:21 +0800</pubDate>
      <link>https://ruby-china.org/topics/41783</link>
      <guid>https://ruby-china.org/topics/41783</guid>
    </item>
    <item>
      <title>Rails 有没有什么好用的 markdown 编辑器</title>
      <description>&lt;p&gt;搜了一下 github，好像没什么比较好的 markdown 编辑器，前几个星星都比较少。因为自己博客（wordpress）用的是 &lt;a href="https://pandao.github.io/editor.md/en.html" rel="nofollow" target="_blank" title=""&gt;editor.md&lt;/a&gt; 这个编辑器，所以对这个编辑器比较有好感，但是用 rails 引入又碰了一鼻子的灰，加上这个编辑器又有两年没更新了，issue 也有四百多个，所以想问下大家有没有什么好点的 markdown 编辑器推荐的，最好对 rails 友好一点&lt;img title=":joy:" alt="😂" src="https://twemoji.ruby-china.com/2/svg/1f602.svg" class="twemoji"&gt; &lt;/p&gt;</description>
      <author>Ian</author>
      <pubDate>Mon, 19 Apr 2021 23:08:33 +0800</pubDate>
      <link>https://ruby-china.org/topics/41163</link>
      <guid>https://ruby-china.org/topics/41163</guid>
    </item>
    <item>
      <title>关于 Rails 6 设置 cookie same site 为 None 的问题</title>
      <description>&lt;p&gt;因为前端 axios 请求 Rails api 登录时（登录标识使用 cookie），响应头提示 &lt;code&gt;This Set-Cookie was blocked because it had the "SameSite=Lax" attribute but come from a cross-site response whith was not the response to a top-level navigation&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;google 得出的结论是要把 "SameSite=Lax" 改为 "SameSite=None" ，但是我试了几个方法都不管用：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;在 &lt;code&gt;config/application.rb&lt;/code&gt; 里边添加一行 &lt;code&gt;config.action_dispatch.cookies_same_site_protection = :none&lt;/code&gt; ，结果无效&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;在 &lt;code&gt;config/initializers/session_store.rb&lt;/code&gt; 里边设置 &lt;code&gt;same_site: :none&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/Ian/20870102-0883-4fe4-884e-e039f9d716fe.png!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;结果运行时报错，提示 &lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ArgumentError (Invalid SameSite value: :none):

rack (2.0.8) lib/rack/utils.rb:260:in `add_cookie_to_header'
actionpack (6.0.1) lib/action_dispatch/middleware/cookies.rb:439:in `block in make_set_cookie_header'
actionpack (6.0.1) lib/action_dispatch/middleware/cookies.rb:437:in `each'
actionpack (6.0.1) lib/action_dispatch/middleware/cookies.rb:437:in `inject'
actionpack (6.0.1) lib/action_dispatch/middleware/cookies.rb:437:in `make_set_cookie_header'
actionpack (6.0.1) lib/action_dispatch/middleware/cookies.rb:423:in `write'
actionpack (6.0.1) lib/action_dispatch/middleware/cookies.rb:653:in `call'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;想请教下应该怎样设置 Same-Site&lt;/p&gt;

&lt;p&gt;登录的 api 是用 &lt;code&gt;grape api&lt;/code&gt; 写的，&lt;code&gt;rails&lt;/code&gt; 使用 docker 部署，使用 nginx 做转发，session_store 使用的是 cache_store，但是我改为 cookie_store 也没有用&lt;/p&gt;

&lt;p&gt;环境： &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ruby 2.6.6&lt;/li&gt;
&lt;li&gt;rails 6.0.1&lt;/li&gt;
&lt;li&gt;grape 1.5.1&lt;/li&gt;
&lt;/ul&gt;</description>
      <author>Ian</author>
      <pubDate>Wed, 07 Apr 2021 15:24:28 +0800</pubDate>
      <link>https://ruby-china.org/topics/41126</link>
      <guid>https://ruby-china.org/topics/41126</guid>
    </item>
  </channel>
</rss>
