<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>2604249649 (unistart)</title>
    <link>https://ruby-china.org/2604249649</link>
    <description></description>
    <language>en-us</language>
    <item>
      <title>爬虫问题：Ruby 对于滑块验证码一般都是怎么处理的</title>
      <description>&lt;p&gt;最近有个任务需要抓取一些数据，这些数据需要登录后才能查看，因此我需要先模拟登录。&lt;/p&gt;

&lt;p&gt;但是我发现登录的时候有滑块验证码需要进行处理，有点不知道怎么弄。&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2604249649/c4079a89-0070-4631-828b-d9f4c63fd1d9.png!large" title="" alt="滑块验证码"&gt;&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;如何识别出缺口的坐标，计算出滑块需要水平移动的距离（识别出缺口需要使用到那些库或者技巧）&lt;/li&gt;
&lt;li&gt;如何模拟滑块移动的轨迹&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;有大佬或前辈，遇到过或解决过这样类似的问题么？&lt;/p&gt;</description>
      <author>2604249649</author>
      <pubDate>Wed, 30 Aug 2023 09:07:39 +0800</pubDate>
      <link>https://ruby-china.org/topics/43295</link>
      <guid>https://ruby-china.org/topics/43295</guid>
    </item>
    <item>
      <title>Roo 格式化单元格值的问题</title>
      <description>&lt;p&gt;我想请教一下各位大佬，Ruby 的&lt;code&gt;Roo&lt;/code&gt;库在读取 execl 时，是如何处理单元格值的格式化问题。&lt;/p&gt;

&lt;p&gt;比如存在像百分比、分数、一些时间日期、货币这些格式的单元格数据，如果保证解析出来的单元格值和显示在 excel 上的单元格值是一样的&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2604249649/b5d19a25-6206-446d-a67c-aa797e8a2823.png!large" title="" alt=""&gt;&lt;/p&gt;</description>
      <author>2604249649</author>
      <pubDate>Wed, 16 Aug 2023 12:06:17 +0800</pubDate>
      <link>https://ruby-china.org/topics/43280</link>
      <guid>https://ruby-china.org/topics/43280</guid>
    </item>
    <item>
      <title>IMGkit 根据 html 生成的图片为什么是一片空白的</title>
      <description>&lt;p&gt;想试一下&lt;code&gt;IMGkit&lt;/code&gt;生成图片的效果，简单的试了一下，但是不知道为什么生成的图片是一片空白，除了表格还在，里面的文字信息都没了
&lt;img src="https://l.ruby-china.com/photo/2604249649/8dc58ad6-6d9f-4432-aebd-2f0bb8b606df.png!large" title="" alt=""&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;#生成image，保存到本地&lt;/span&gt;
&lt;span class="n"&gt;image_html_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'/Users/unistart/Documents/stock_suggest/generate-image2.html'&lt;/span&gt;
&lt;span class="n"&gt;image_html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image_html_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;IMGKit&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;image_html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;quality: &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;format: :jpg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;height: &lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stylesheets&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s1"&gt;'/Users/unistart/Documents/stock_suggest/image.css'&lt;/span&gt;
&lt;span class="n"&gt;image_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"/Users/unistart/Pictures/image_&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%F-%T'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.jpg"&lt;/span&gt;
&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我是有哪里用的不对么，没明白为什么 html 表格中的文字信息，输出为图片时就都没了&lt;/p&gt;</description>
      <author>2604249649</author>
      <pubDate>Mon, 14 Aug 2023 17:51:33 +0800</pubDate>
      <link>https://ruby-china.org/topics/43276</link>
      <guid>https://ruby-china.org/topics/43276</guid>
    </item>
    <item>
      <title>Ruby 对 Excel 文件的处理能力是不是弱了点</title>
      <description>&lt;p&gt;目前使用的 Excel 读取库是 Roo，目前在处理读入时遇到了问题&lt;/p&gt;

&lt;p&gt;目前读入 excel 的时候是一行一行读入的，读取行信息时，使用的是 Roo 库的&lt;code&gt;row&lt;/code&gt;方法或者&lt;code&gt;each_row_streaming&lt;/code&gt;方法来进行处理。&lt;/p&gt;
&lt;h2 id="问题"&gt;问题&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt; row 方法读取行数据时，返回的列数是固定的，如果当前的 sheet 页存在多个列数不同的表格，这样一行行读取时返回的行数据就不对&lt;/li&gt;
&lt;li&gt; each_row_streaming 方法去读行数据时，列数是根据当前行实际有列数来的，但是还是有一个问题：表格之间存在的空行识别效果不好，会有空行丢失的情况&lt;/li&gt;
&lt;li&gt; row 和 each_row_streaming 在遍历行数据时，貌似没有提供能够判断当前行的单元格是否存在合并的方法或者解决方案&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ruby 有 excel 处理库能够做到像 Java 的&lt;code&gt;POI&lt;/code&gt;那样的处理么？&lt;/p&gt;</description>
      <author>2604249649</author>
      <pubDate>Thu, 10 Aug 2023 17:58:37 +0800</pubDate>
      <link>https://ruby-china.org/topics/43267</link>
      <guid>https://ruby-china.org/topics/43267</guid>
    </item>
    <item>
      <title>Ruby 有那个操作 excel 的库支持在读取 excel 内容时获取单元格样式信息么？</title>
      <description>&lt;p&gt;目前遇到一个功能：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;模版导出：只有第一次导出是一个固定的空模版，之后的导出模版内容都是上一次导入的，文件导出格式是 xlsx，之后导入也是&lt;/li&gt;
&lt;li&gt;模版导入：用户在导出的模版上做操作，可能会在工作页上已有的表格上加行或加表格，同时可能会给单元格样式信息&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;遇到的问题：
在使用&lt;code&gt;Roo Gem&lt;/code&gt;  读取 excel 文件时，发现好像只能取到单元格的内容，但是单元格的样式信息好像没有提供相应的方法获取，项目中用到的和 Excel 相关的&lt;code&gt;Gem&lt;/code&gt;有：&lt;code&gt;axlsx&lt;/code&gt;、&lt;code&gt;roo&lt;/code&gt;、&lt;code&gt;creek&lt;/code&gt; 、&lt;code&gt;spreadsheet&lt;/code&gt;，这些库中有读 excel 能力的库好像都没有对获取单元格样式的方法或者相关的说明，或者不支持对&lt;code&gt;xlsx&lt;/code&gt;文件的处理&lt;/p&gt;

&lt;p&gt;期望：
希望能有一个&lt;code&gt;Ruby&lt;/code&gt;操作 Excel 库，能够像&lt;code&gt;Java&lt;/code&gt;的&lt;code&gt;POI&lt;/code&gt;一样有提供类似于&lt;code&gt;getCellStyle&lt;/code&gt;这样的方法&lt;/p&gt;</description>
      <author>2604249649</author>
      <pubDate>Wed, 02 Aug 2023 10:13:28 +0800</pubDate>
      <link>https://ruby-china.org/topics/43250</link>
      <guid>https://ruby-china.org/topics/43250</guid>
    </item>
    <item>
      <title>想请教一下关于 Rails7 中关于集成测试的一个问题</title>
      <description>&lt;h2 id="环境"&gt;环境&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;ruby version: 3.2.2&lt;/li&gt;
&lt;li&gt;rails version: 7.0.4.3&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="问题"&gt;问题&lt;/h2&gt;
&lt;p&gt;我按照《Ruby on Rails 教程》一书，使用 cookies 完成记住用户的功能，但是之后进行集成测试时发生了如下错误：&lt;/p&gt;

&lt;p&gt;signed 方法找不到&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;ERROR&lt;/span&gt; &lt;span class="no"&gt;UsersLoginTest&lt;/span&gt;&lt;span class="c1"&gt;#test_login_with_valid_information_followed_by_logout (3.96s)&lt;/span&gt;
&lt;span class="no"&gt;Minitest&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;UnexpectedError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;      &lt;span class="no"&gt;NoMethodError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;undefined&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt; &lt;span class="sb"&gt;`signed' for #&amp;lt;Rack::Test::CookieJar:0x00007f6e07adc6f0
  ......
            app/helpers/sessions_helper.rb:14:in `&lt;/span&gt;&lt;span class="n"&gt;current_user&lt;/span&gt;&lt;span class="s1"&gt;'
            app/helpers/sessions_helper.rb:25:in `logged_in?'&lt;/span&gt;
            &lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;integration&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;users_login_test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;38&lt;/span&gt;&lt;span class="ss"&gt;:in&lt;/span&gt; &lt;span class="sb"&gt;`block in &amp;lt;class:UsersLoginTest&amp;gt;'
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;相关内容如下：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;集成测试 test/integration/users_logn_test.rb 文件&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UsersLoginTest&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActionDispatch&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;IntegrationTest&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;

  &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="s2"&gt;"login with valid information followed by logout"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="n"&gt;login_path&lt;/span&gt;
    &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="n"&gt;login_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;params: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;session: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;email: &lt;/span&gt;&lt;span class="vi"&gt;@user.email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;password: &lt;/span&gt;&lt;span class="s2"&gt;"password"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;assert_redirected_to&lt;/span&gt; &lt;span class="vi"&gt;@user&lt;/span&gt; &lt;span class="c1"&gt;# 检查重定向地址是否正确&lt;/span&gt;
    &lt;span class="n"&gt;follow_redirect!&lt;/span&gt; &lt;span class="c1"&gt;# 访问重定向地址&lt;/span&gt;
    &lt;span class="n"&gt;assert_select&lt;/span&gt; &lt;span class="s2"&gt;"a[href=?]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;login_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;count: &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;assert_select&lt;/span&gt; &lt;span class="s2"&gt;"a[href=?]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;logout_path&lt;/span&gt;
    &lt;span class="n"&gt;assert_select&lt;/span&gt; &lt;span class="s2"&gt;"a[href=?]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;logout_path&lt;/span&gt;
    &lt;span class="n"&gt;assert_not&lt;/span&gt; &lt;span class="n"&gt;logged_in?&lt;/span&gt;
    &lt;span class="n"&gt;assert_redirected_to&lt;/span&gt; &lt;span class="n"&gt;root_url&lt;/span&gt;
    &lt;span class="n"&gt;follow_redirect!&lt;/span&gt;
    &lt;span class="n"&gt;assert_select&lt;/span&gt; &lt;span class="s2"&gt;"a[href=?]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;login_path&lt;/span&gt;
    &lt;span class="n"&gt;assert_select&lt;/span&gt; &lt;span class="s2"&gt;"a[href=?]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;logout_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;count: &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;assert_select&lt;/span&gt; &lt;span class="s2"&gt;"a[href=?]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ss"&gt;count: &lt;/span&gt;&lt;span class="mi"&gt;0&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;ul&gt;
&lt;li&gt;辅助模块 app/helpers/sessions_helper.rb&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;SessionsHelper&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;log_in&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="c1"&gt;# 利用Rails提供的session方法在浏览器中创建一个临时cookie，内容是加密后的用户ID&lt;/span&gt;
    &lt;span class="c1"&gt;# 后续请求中，可以使用session[:user_id]取回这个ID&lt;/span&gt;
    &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&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;id&lt;/span&gt;
  &lt;span class="k"&gt;end&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;current_user&lt;/span&gt;
    &lt;span class="c1"&gt;# 如果session[:user_id]中有用户ID，就使用其检索用户&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
      &lt;span class="vi"&gt;@current_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_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;id: &lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cookies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signed&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;# 否则检查cookies[:user_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_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;id: &lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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;authenticated?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cookies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:remember_token&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="n"&gt;log_in&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="c1"&gt;# 将用户ID存入session&lt;/span&gt;
        &lt;span class="vi"&gt;@current_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# 判断用户是否已经登录，已登录返回true，否则返回false&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;logged_in?&lt;/span&gt;
    &lt;span class="o"&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="nf"&gt;nil?&lt;/span&gt;
  &lt;span class="k"&gt;end&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;log_out&lt;/span&gt;
    &lt;span class="n"&gt;forget&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="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 从会话中删除用户ID&lt;/span&gt;
    &lt;span class="vi"&gt;@current_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&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;end&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;remember&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;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remember&lt;/span&gt; &lt;span class="c1"&gt;# 为用户生成一个记忆令牌，并将其摘要记录到数据库记录中&lt;/span&gt;
    &lt;span class="c1"&gt;# permanent方法用于设置当前cookie的过期时间为20年后，signed方法用于对cookie值进行签名和加密&lt;/span&gt;
    &lt;span class="n"&gt;cookies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;permanent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signed&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt; &lt;span class="c1"&gt;# 对用户ID进行签名和加密&lt;/span&gt;
    &lt;span class="n"&gt;cookies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;permanent&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:remember_token&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remember_token&lt;/span&gt;
  &lt;span class="k"&gt;end&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;forget&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;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forget&lt;/span&gt;
    &lt;span class="c1"&gt;# 删除cookie&lt;/span&gt;
    &lt;span class="n"&gt;cookies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;cookies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:remember_token&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;ul&gt;
&lt;li&gt;相关的控制器 app/controllers/sessions_controller.rb&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SessionsController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&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_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;email: &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;:session&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;downcase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;respond_to&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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;authenticate&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;:session&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="ss"&gt;:password&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="c1"&gt;# 保存用户登录信息&lt;/span&gt;
        &lt;span class="n"&gt;log_in&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
        &lt;span class="n"&gt;remember&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
        &lt;span class="c1"&gt;# 用户登录成功，重定向到用户资料页面&lt;/span&gt;
        &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="c1"&gt;# flash闪现消息在一个请求的生命周期内是持续存在的，但是重新渲染页面不算一次新的请求&lt;/span&gt;
        &lt;span class="c1"&gt;# 因为使用flash.now代替（flash.now专门用于在重新渲染的页面中显示闪现消息）&lt;/span&gt;
        &lt;span class="n"&gt;flash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:danger&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Log in failed, please check your email and password!"&lt;/span&gt;
        &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:new&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;status: :bad_request&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;destroy&lt;/span&gt;
    &lt;span class="n"&gt;log_out&lt;/span&gt;
    &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;root_url&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;a href="https://stackoverflow.com/questions/43690796/setup-cookie-signed-in-rails-5-controller-integration-tests" rel="nofollow" target="_blank" title=""&gt;stackoverflow&lt;/a&gt;上看到有一个类似的问题，但是解决方案对我不起作用。同时我翻了一下&lt;a href="https://github.com/rails/rails/issues?q=is%3Aissue+cookies+signed" rel="nofollow" target="_blank" title=""&gt;Rails issues&lt;/a&gt;列表，找到了一个类似的问题&lt;a href="https://github.com/rails/rails/issues/27145" rel="nofollow" target="_blank" title=""&gt;Signed cookies not available in controller tests&lt;/a&gt;看了一遍，也没找到合适解决的方案，说是集成测试不能访问加密后的 cookies，我点搞不懂了。&lt;/p&gt;

&lt;p&gt;有大佬知道怎么解决上面这个问题么？谢谢&lt;/p&gt;</description>
      <author>2604249649</author>
      <pubDate>Sun, 07 May 2023 17:35:20 +0800</pubDate>
      <link>https://ruby-china.org/topics/43057</link>
      <guid>https://ruby-china.org/topics/43057</guid>
    </item>
    <item>
      <title>关于 Rails 中辅助方法在视图中使用的一个小问题</title>
      <description>&lt;p&gt;我在《Ruby on Rails 教程（第四版）》8.2.2 节中看到书上做了如下操作，但是我模仿着做了，但是没有效果&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;书籍首先在 ApplicationController 中引入 Sessions 辅助模块&lt;/li&gt;
&lt;/ul&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="n"&gt;protect_from_forgery&lt;/span&gt; &lt;span class="ss"&gt;with: :exception&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;SessionsHelper&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt; 然后在 SessionsHelper 中首先创建如下辅助方法&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;SessionsHelper&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;log_in&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="c1"&gt;# 利用Rails提供的session方法在浏览器中创建一个临时cookie，内容是加密后的用户ID&lt;/span&gt;
    &lt;span class="c1"&gt;# 后续请求中，可以使用session[:user_id]取回这个ID&lt;/span&gt;
    &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&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;id&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;ul&gt;
&lt;li&gt;接着在 SessionsController 中进行用户登录处理&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SessionsController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&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_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;email: &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;:session&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;downcase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;respond_to&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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;authenticate&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;:session&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="ss"&gt;:password&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="c1"&gt;# 保存用户登录信息&lt;/span&gt;
        &lt;span class="n"&gt;log_in&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
        &lt;span class="c1"&gt;# 用户登录成功，重定向到用户资料页面&lt;/span&gt;
        &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="c1"&gt;# flash闪现消息在一个请求的生命周期内是持续存在的，但是重新渲染页面不算一次新的请求&lt;/span&gt;
        &lt;span class="c1"&gt;# 因为使用flash.now代替（flash.now专门用于在重新渲染的页面中显示闪现消息）&lt;/span&gt;
        &lt;span class="n"&gt;flash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:danger&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Log in failed, please check your email and password!"&lt;/span&gt;
        &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:new&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;status: :bad_request&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;destroy&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;ul&gt;
&lt;li&gt;接着又继续创建了两个辅助方法，一个用于获取当前登录用户，另一个用于获取用户登录状态&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;SessionsHelper&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;log_in&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="c1"&gt;# 利用Rails提供的session方法在浏览器中创建一个临时cookie，内容是加密后的用户ID&lt;/span&gt;
    &lt;span class="c1"&gt;# 后续请求中，可以使用session[:user_id]取回这个ID&lt;/span&gt;
    &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&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;id&lt;/span&gt;
  &lt;span class="k"&gt;end&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;current_user&lt;/span&gt;
    &lt;span class="vi"&gt;@current_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_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;id: &lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# 判断用户是否已经登录，已登录返回true，否则返回false&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;logged_in?&lt;/span&gt;
    &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="vi"&gt;@current_user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nil?&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;ul&gt;
&lt;li&gt;最后就是我不太理解的地方了：它在视图进行了如下修改，希望达到已登录用户和未登录用户看到的导航栏连接不同的效果&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;logged_in?&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;link_to&lt;/span&gt; &lt;span class="s2"&gt;"Users"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'#'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;class: &lt;/span&gt;&lt;span class="s2"&gt;"nav-link"&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-item dropdown"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-link dropdown-toggle"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;data-bs-toggle=&lt;/span&gt;&lt;span class="s"&gt;"dropdown"&lt;/span&gt; &lt;span class="na"&gt;aria-expanded=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        Account
      &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"dropdown-menu"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
          &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;link_to&lt;/span&gt; &lt;span class="s2"&gt;"Profile"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;class: &lt;/span&gt;&lt;span class="s2"&gt;"dropdown-item"&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
          &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;link_to&lt;/span&gt; &lt;span class="s2"&gt;"Settings"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'#'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;class: &lt;/span&gt;&lt;span class="s2"&gt;"dropdown-item"&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;hr&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"dropdown-divider"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
          &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;link_to&lt;/span&gt; &lt;span class="s2"&gt;"Log out"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;logout_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;method: &lt;/span&gt;&lt;span class="s2"&gt;"delete"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;class: &lt;/span&gt;&lt;span class="s2"&gt;"dropdown-item"&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;link_to&lt;/span&gt; &lt;span class="s2"&gt;"Log in"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;login_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;class: &lt;/span&gt;&lt;span class="s2"&gt;"nav-link"&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我试了书上的操作，发现登录后用户看到的导航链接根本没有变（辅助方法&lt;code&gt;current_user&lt;/code&gt;和&lt;code&gt;logged_in?&lt;/code&gt;貌似没有起到作用），通过&lt;code&gt;debugger&lt;/code&gt;断点发现辅助方法中创建的&lt;code&gt;@current_user对象&lt;/code&gt;在转到用户资料页面后就是&lt;code&gt;nil&lt;/code&gt;了，所以用户登录后看到的链接不会变。&lt;/p&gt;

&lt;p&gt;我改成了下面这样，效果是有了，&lt;strong&gt;但是我想知道书上之前那样写的操作为什么达不到效果&lt;/strong&gt;。&lt;/p&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;link_to&lt;/span&gt; &lt;span class="s2"&gt;"Users"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'#'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;class: &lt;/span&gt;&lt;span class="s2"&gt;"nav-link"&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-item dropdown"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-link dropdown-toggle"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;data-bs-toggle=&lt;/span&gt;&lt;span class="s"&gt;"dropdown"&lt;/span&gt; &lt;span class="na"&gt;aria-expanded=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         Account
       &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"dropdown-menu"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
           &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;link_to&lt;/span&gt; &lt;span class="s2"&gt;"Profile"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;class: &lt;/span&gt;&lt;span class="s2"&gt;"dropdown-item"&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
           &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;link_to&lt;/span&gt; &lt;span class="s2"&gt;"Settings"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'#'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;class: &lt;/span&gt;&lt;span class="s2"&gt;"dropdown-item"&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;hr&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"dropdown-divider"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
           &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;link_to&lt;/span&gt; &lt;span class="s2"&gt;"Log out"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;logout_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;method: &lt;/span&gt;&lt;span class="s2"&gt;"delete"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;class: &lt;/span&gt;&lt;span class="s2"&gt;"dropdown-item"&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
   &lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;link_to&lt;/span&gt; &lt;span class="s2"&gt;"Log in"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;login_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;class: &lt;/span&gt;&lt;span class="s2"&gt;"nav-link"&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
   &lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;

&lt;p&gt;UsersController 控制器的 show 动作会处理用户资料页面的显示&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;UsersController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
   &lt;span class="o"&gt;...&lt;/span&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="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="c1"&gt;# .authenticate("123456")&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

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

&lt;/code&gt;&lt;/pre&gt;</description>
      <author>2604249649</author>
      <pubDate>Thu, 04 May 2023 17:16:09 +0800</pubDate>
      <link>https://ruby-china.org/topics/43051</link>
      <guid>https://ruby-china.org/topics/43051</guid>
    </item>
    <item>
      <title>关于 Rails7 中 redirect_to 的一个小问题</title>
      <description>&lt;p&gt;按道理在 Rails 中这两行代码不应该是等价的么
&lt;code&gt;redirect_to @user&lt;/code&gt;和&lt;code&gt;redirect_to user_url(@user)&lt;/code&gt;，但是在我在 Rails7 中使用时，两者重定向地址貌似不一样，不知道是什么原因导致的。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;redirect_to @user&lt;/code&gt;会重定向到&lt;code&gt;http://localhost:3000/users/id&lt;/code&gt;
&lt;img src="https://l.ruby-china.com/photo/2604249649/7952a8cd-ce5c-4855-b1ed-82b2d8dc2bff.png!large" title="" alt=""&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;redirect_to user_url(@user)&lt;/code&gt;会重定向到&lt;code&gt;http://localhost:3000/users.id&lt;/code&gt;
&lt;img src="https://l.ruby-china.com/photo/2604249649/b433e7b4-c480-468f-86ab-58f6b4925012.png!large" title="" alt=""&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;p&gt;部分代码&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;new.html.erb（参考&lt;a href="" title=""&gt;Error: Form responses must redirect to another location&lt;/a&gt;多套了一个&lt;code&gt;turbo_frame_tag&lt;/code&gt;）&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;%#  用户注册页面 %&amp;gt;
&amp;lt;%= provide(:title, "Sign up") %&amp;gt;
&amp;lt;h1&amp;gt;Sign up&amp;lt;/h1&amp;gt;

&amp;lt;div class="row"&amp;gt;
  &amp;lt;div class="col-md-6 mx-auto"&amp;gt;
    &amp;lt;%= turbo_frame_tag "post" do %&amp;gt;
      &amp;lt;%= form_for(@user, url: signup_path) do |f| %&amp;gt;
        &amp;lt;%= render 'shared/error_messages' %&amp;gt;

        &amp;lt;%= f.label :name, class: "form-label" %&amp;gt;
        &amp;lt;%= f.text_field :name, class: "form-control" %&amp;gt;

        &amp;lt;%= f.label :email, class: "form-label mt-3" %&amp;gt;
        &amp;lt;%= f.email_field :email, class: "form-control" %&amp;gt;

        &amp;lt;%= f.label :password, class: "form-label mt-3" %&amp;gt;
        &amp;lt;%= f.password_field :password, class: "form-control" %&amp;gt;

        &amp;lt;%= f.label :password_confirmation, "Confirmation", class: "form-label mt-3" %&amp;gt;
        &amp;lt;%= f.password_field :password_confirmation, class: "form-control" %&amp;gt;

        &amp;lt;div class="d-grid gap-1 mt-4"&amp;gt;
          &amp;lt;%= f.submit "Create my account", class: "btn btn-outline-primary" %&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;% end %&amp;gt;
    &amp;lt;% end %&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;UsersController.rb&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def create
@user = User.new(user_params)

# respond_to do |format|
#   if @user.save
#     # redirect_to @user
#     format.html { redirect_to @user, notice: 'User account was successfully created.' }
#     format.json { render :show, status: :created, location: @user }
#   else
#     # 处理注册失败的情况
#     format.html { render :new }
#     format.json { render json: @user.errors, status: :unprocessable_entity }
#   end
# end

if @user.save
  # redirect_to users_url(@user)
  redirect_to @user
else
  render 'new'
end
end
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;routes.rb&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Rails.application.routes.draw do
# Defines the root path route ("/”）
root "static_pages#home"
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
get '/help', to: 'static_pages#help'
get '/about', to: 'static_pages#about'
get '/contact', to: 'static_pages#contact'
#用户注册路由
get '/signup', to: 'users#new'
post '/signup', to: 'users#create'
resources :users
end
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;有大佬知道这是什么原因导致的么？&lt;/p&gt;</description>
      <author>2604249649</author>
      <pubDate>Mon, 01 May 2023 09:00:51 +0800</pubDate>
      <link>https://ruby-china.org/topics/43042</link>
      <guid>https://ruby-china.org/topics/43042</guid>
    </item>
    <item>
      <title>关于把代码块转换为 Proc 的问题</title>
      <description>&lt;p&gt;我看元编程一书在 4.5 节介绍了可调用对象，对书里的有些描述感到有些困惑。&lt;/p&gt;

&lt;p&gt;1、Proc 对象产生的方式有几种&lt;/p&gt;

&lt;p&gt;&lt;img src="https://i.imgur.com/GXU7vTn.png" title="" alt="书上说已经介绍了四种"&gt;&lt;/p&gt;

&lt;p&gt;书上说已经介绍了四种，但是我怎么只看到了三种：使用&lt;strong&gt;Proc.new 一种&lt;/strong&gt;，&lt;strong&gt;lambda 一种&lt;/strong&gt;，&lt;strong&gt;-&amp;gt;lambda 操作符一种&lt;/strong&gt;，所以 Proc 对象到底有几种产生方式&lt;/p&gt;

&lt;p&gt;2、&amp;amp;操作符&lt;/p&gt;

&lt;p&gt;&lt;img src="https://i.imgur.com/I6WFo53.png" title="" alt="&amp;amp;操作符的作用"&gt;&lt;/p&gt;

&lt;p&gt;&amp;amp;操作符的作用到底是将 Proc 对象转为代码块使用，还是将代码块转为 Proc 对象使用&lt;/p&gt;

&lt;p&gt;我有点搞懵了，有大佬能指点我一下么？&lt;/p&gt;</description>
      <author>2604249649</author>
      <pubDate>Fri, 03 Mar 2023 16:14:25 +0800</pubDate>
      <link>https://ruby-china.org/topics/42920</link>
      <guid>https://ruby-china.org/topics/42920</guid>
    </item>
    <item>
      <title>关于 Ruby 中 respond_to_mssing 的一点困惑</title>
      <description>&lt;p&gt;Ruby 元编程一书中有提到了使用 respond_to? 可以询问对象是否能够响应对应方法，当一个方法没有定义时 respond_to? 会调用 respond_to_missing? 方法来返回结果&lt;/p&gt;

&lt;p&gt;我看了一下 respond_to_missing? 的方法说明，感觉没太看明白。&lt;/p&gt;

&lt;p&gt;主要这句说明："Hook method to return whether the obj can respond to id method or not. "，这个钩子函数是什么意思？还有就是我如果不覆写 respond_to_missing？方法的话，当我询问一个幽灵方法时，它会返回一个 false，不是很理解（至少函数说明中没有明确说明）&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;Demo&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="k"&gt;super&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s1"&gt;'hello'&lt;/span&gt;
    &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="s2"&gt;"method name: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, args: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;respond_to_missing?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;include_private&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kp"&gt;false&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;exists_method&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;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Demo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hello&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="c1"&gt;# 成功调用&lt;/span&gt;
&lt;span class="c1"&gt;# a.hello2  # 抛出NoMethodError&lt;/span&gt;

&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="s2"&gt;"respond_to: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;respond_to?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'exists_method'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;   &lt;span class="c1"&gt;#=&amp;gt; true&lt;/span&gt;
&lt;span class="c1"&gt;# 在调用 respond_to? 方法时，如果方法是一个幽灵方法，它会调用 respond_to_missing? 方法确定返回值&lt;/span&gt;
&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="s2"&gt;"respond_to: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;respond_to?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'hello'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;#=&amp;gt; false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;</description>
      <author>2604249649</author>
      <pubDate>Sat, 25 Feb 2023 16:39:45 +0800</pubDate>
      <link>https://ruby-china.org/topics/42908</link>
      <guid>https://ruby-china.org/topics/42908</guid>
    </item>
    <item>
      <title>关于私有方法调用的问题</title>
      <description>&lt;p&gt;我最近重新再看《Ruby 元编程（第二版）》，在 2.4 节有如下说明：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;私有方法服从一条简单的规则：&lt;strong&gt;不能明确指定接收者来调用私有方法&lt;/strong&gt;。换而言之，&lt;strong&gt;私有方法只能通过隐性的接收者 self 调用&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;然后还举了一个例子&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;C&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;public_method&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;private_method&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;private_method&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="no"&gt;C&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="nf"&gt;public_method&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后又有如下说明：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;如果去掉 self 关键字，代码就可以正常运行了。这个例子说明私有方法同时遵循两条规则：首先，如果调用方法的接收者不是自己，就必须明确指明接收者；其次，私有方法只能通过隐性接收者调用。根据这两条规则，你只能在自身中调用私有方法。这条规则称为&lt;strong&gt;私有规则&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;我的疑惑如下：&lt;/p&gt;

&lt;p&gt;1.我在 Ruby3 的环境下试了一下例子，貌似加不加 self 都没报错，可以调用，Ruby3 是对这块做了改动么？&lt;/p&gt;

&lt;p&gt;2.还有就是如果按照 Ruby2 的版本来理解，我还是不太明白书上说的意思：前面说私有方法的调用不能明确指定接收者来调用，后面又说如果调用方法的接收者不是自己，就必须明确指定接收者，而且私有方法只能通过隐性的接收者调用。&lt;/p&gt;

&lt;p&gt;我感觉有点懵了，有大佬能有更简明的说法或者更直白的示例么？&lt;/p&gt;

&lt;p&gt;补充：我在 replit 用 ruby2.7 试了一下，也没报错
&lt;img src="https://cdn.unistart.top/screenshot/Snipaste_2023-02-23_15-53-48.png" title="" alt="replit上的截图"&gt;&lt;/p&gt;</description>
      <author>2604249649</author>
      <pubDate>Thu, 23 Feb 2023 15:51:33 +0800</pubDate>
      <link>https://ruby-china.org/topics/42903</link>
      <guid>https://ruby-china.org/topics/42903</guid>
    </item>
    <item>
      <title>[codewars] 上一道关于摩斯电码的习题 我看了答案也没想明白</title>
      <description>&lt;p&gt;原题链接：&lt;a href="https://www.codewars.com/kata/54b72c16cd7f5154e9000457/ruby" rel="nofollow" target="_blank" title=""&gt;Decode the Morse code, advance&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;本题的关键是要找出&lt;strong&gt;比特串的传输速率&lt;/strong&gt;，我想了很久也没想明白，然后我看了答案之后就更不明白了&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bits&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="sr"&gt;/1+|0+/&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt; &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;答案大多使用类似上面的方法来求出比特串的传输率，&lt;strong&gt;我没明白为啥找到 0 串和 1 串长度最小的那个就一定是当前比特串的传输速率&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;有大佬知道这题比特串的传输率到底是怎么求的么？&lt;/p&gt;</description>
      <author>2604249649</author>
      <pubDate>Sun, 25 Dec 2022 13:34:05 +0800</pubDate>
      <link>https://ruby-china.org/topics/42806</link>
      <guid>https://ruby-china.org/topics/42806</guid>
    </item>
    <item>
      <title>[新手提问] 关于 include 和 prepend 的问题</title>
      <description>&lt;p&gt;我看到《Ruby 元编程（第二版）》中关于&lt;strong&gt;多重包含&lt;/strong&gt;有如下介绍：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;u&gt;&lt;strong&gt;每次 include 或 prepend 一个模块的时候，如果该模块已经存在于祖先链中，那么 Ruby 会悄悄地忽略这个包含&lt;/strong&gt;（include 或 prepend）指令&lt;/u&gt;。因此一个模块只会在一条祖先链中出现一次。这种处理方式也许会在未来的 Ruby 版本中改变，但你暂时不用为它担心。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;但是我自己试了一下发现貌似不太一样，我的 ruby 环境是 ruby3.1.2，书好像用的是 Ruby2.x&lt;/p&gt;

&lt;p&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;M1&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;module&lt;/span&gt; &lt;span class="nn"&gt;M2&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;M1&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;M3&lt;/span&gt;
  &lt;span class="n"&gt;prepend&lt;/span&gt; &lt;span class="no"&gt;M1&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;M2&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="no"&gt;M3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ancestors&lt;/span&gt; &lt;span class="c1"&gt;#=&amp;gt; [M1, M3, M2]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我对照的书上的示例改了一下代码，交换了 include 和 prepend 的顺序&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;M1&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;module&lt;/span&gt; &lt;span class="nn"&gt;M2&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;M1&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;M3&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;M2&lt;/span&gt; &lt;span class="c1"&gt;# 交换了 include 和 prepend 的顺序&lt;/span&gt;
  &lt;span class="n"&gt;prepend&lt;/span&gt; &lt;span class="no"&gt;M1&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="no"&gt;M3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ancestors&lt;/span&gt; &lt;span class="c1"&gt;#=&amp;gt; [M1, M3, M2, M1]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输出结果中 M1 在祖先链中出现了两次，这和书上说的不一致，没明白这是为啥？有 Ruby 高手或者大佬能给萌新解释一下么？&lt;/p&gt;</description>
      <author>2604249649</author>
      <pubDate>Thu, 01 Dec 2022 15:45:04 +0800</pubDate>
      <link>https://ruby-china.org/topics/42774</link>
      <guid>https://ruby-china.org/topics/42774</guid>
    </item>
  </channel>
</rss>
