<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>y9info (&amp;全靠AI写代码)</title>
    <link>https://ruby-china.org/y9info</link>
    <description>一心一意、再接再厉、三省吾身、名扬四海、学富五车、六韬三略、七步才华、才高八斗、九天揽月、十年磨剑。自学rails，略感小成，至三省吾身，孜孜不倦，他日方可九天揽月。</description>
    <language>en-us</language>
    <item>
      <title>rails7.1 以后版本，使用 activestorage 在 update 对象过程中，追加附件而不删除已有附件的方法</title>
      <description>&lt;h4 id="问题：升级rails7.1后版本后，config.active_storage.replace_on_assign_to_many = true 来实现active_storage增加附件，而不是覆盖已有附件的方法已经被取消，新的解决方案是什么？"&gt;问题：升级 rails7.1 后版本后，config.active_storage.replace_on_assign_to_many = true 来实现 active_storage 增加附件，而不是覆盖已有附件的方法已经被取消，新的解决方案是什么？&lt;/h4&gt;&lt;h4 id="回答： 在控制器中使用“attach”方法，大致思路是，从前端传过来的参数hash列表中，update先剔除附件参数，对增加的附件参数，单独适用attach方法升级到附件列表中。参考代码如下："&gt;回答：在控制器中使用“attach”方法，大致思路是，从前端传过来的参数 hash 列表中，update 先剔除附件参数，对增加的附件参数，单独适用 attach 方法升级到附件列表中。参考代码如下：&lt;/h4&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;Post&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
   &lt;span class="n"&gt;has_many_attached&lt;/span&gt; &lt;span class="ss"&gt;:images&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;控制器 update 方法变更后：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update&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="vi"&gt;@post.update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post_params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reject&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"images"&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="n"&gt;post_params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:images&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;present?&lt;/span&gt;
       &lt;span class="n"&gt;post_params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:images&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
         &lt;span class="vi"&gt;@post.images.attach&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="k"&gt;end&lt;/span&gt;
     &lt;span class="k"&gt;end&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="vi"&gt;@post&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;notice: &lt;/span&gt;&lt;span class="s1"&gt;'Post was successfully updated.'&lt;/span&gt; &lt;span class="p"&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;json&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;:show&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;status: :ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;location: &lt;/span&gt;&lt;span class="vi"&gt;@post&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="k"&gt;else&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;:edit&lt;/span&gt; &lt;span class="p"&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;json&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;json: &lt;/span&gt;&lt;span class="vi"&gt;@post.errors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;status: :unprocessable_entity&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;/code&gt;&lt;/pre&gt;</description>
      <author>y9info</author>
      <pubDate>Mon, 23 Dec 2024 14:53:36 +0800</pubDate>
      <link>https://ruby-china.org/topics/43986</link>
      <guid>https://ruby-china.org/topics/43986</guid>
    </item>
    <item>
      <title>这个怎么解？Puma starting in single mode...</title>
      <description>&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;rails&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Booting&lt;/span&gt; &lt;span class="no"&gt;Puma&lt;/span&gt;

&lt;span class="o"&gt;***&lt;/span&gt; &lt;span class="no"&gt;SIGUSR2&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;implemented&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt; &lt;span class="n"&gt;based&lt;/span&gt; &lt;span class="n"&gt;restart&lt;/span&gt; &lt;span class="n"&gt;unavailable!&lt;/span&gt;
&lt;span class="o"&gt;***&lt;/span&gt; &lt;span class="no"&gt;SIGUSR1&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;implemented&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt; &lt;span class="n"&gt;based&lt;/span&gt; &lt;span class="n"&gt;restart&lt;/span&gt; &lt;span class="n"&gt;unavailable!&lt;/span&gt;
&lt;span class="o"&gt;***&lt;/span&gt; &lt;span class="no"&gt;SIGHUP&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;implemented&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt; &lt;span class="n"&gt;based&lt;/span&gt; &lt;span class="n"&gt;logs&lt;/span&gt; &lt;span class="n"&gt;reopening&lt;/span&gt; &lt;span class="n"&gt;unavailable!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;之前程序都比较正常，开发模式启动都可以正常跑，这几天发现一个问题，就是“假死”状态，正常打开网页也没问题，只是偶尔出现（感觉是点击太快或是查询太多？）打开网页后既不报错，但是也无法打开，命令行窗口也不刷新日志内容，就这样停滞在那里，也不动弹。这种假死状态不是固定的，同样的页面，刚才是假死的，重新启动后，就不假死了，但是又可能在下面某一个页面出现类似的问题。
我怀疑是上述“Puma starting in single mode”的问题，但是我没有证据，也不知道怎么入手，不知道上面几个提示怎么解释？
查了 puma.rb 线程这里也没啥问题。&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;max_threads_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"RAILS_MAX_THREADS"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;min_threads_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"RAILS_MIN_THREADS"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;max_threads_count&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;threads&lt;/span&gt; &lt;span class="n"&gt;min_threads_count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_threads_count&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;</description>
      <author>y9info</author>
      <pubDate>Wed, 21 Aug 2024 11:42:08 +0800</pubDate>
      <link>https://ruby-china.org/topics/43861</link>
      <guid>https://ruby-china.org/topics/43861</guid>
    </item>
    <item>
      <title>区别于 RBAC，使用一种权限标签方法来设置用户权限的初步思考</title>
      <description>&lt;h4 id="通常的的RBAC权限方式，其基本思路是，赋予角色身份某种权限，用户在获取角色身份的同时，取得相应权限。这种抽象方式，符合日常经验，本身也有合理性。"&gt;通常的的 RBAC 权限方式，其基本思路是，赋予角色身份某种权限，用户在获取角色身份的同时，取得相应权限。这种抽象方式，符合日常经验，本身也有合理性。&lt;/h4&gt;&lt;h4 id="但是有一点问题是，“权限溢出”时不够灵活，譬如销售员有确定价格、制作合同、签署合同的权限，财务人员有收款、开具发票的权限，但是在某些时候（譬如派到外地去临时开拓业务），我们希望赋予销售员临时收款权限，这时候需要变更销售员的角色才能实现，或者设置另外一个RoleB类销售员的角色才能实现，在这种权限需要溢出时不够灵活。"&gt;但是有一点问题是，“权限溢出”时不够灵活，譬如销售员有确定价格、制作合同、签署合同的权限，财务人员有收款、开具发票的权限，但是在某些时候（譬如派到外地去临时开拓业务），我们希望赋予销售员临时收款权限，这时候需要变更销售员的角色才能实现，或者设置另外一个 RoleB 类销售员的角色才能实现，在这种权限需要溢出时不够灵活。&lt;/h4&gt;&lt;h4 id="同样的道理，假如我们希望新入职未过试用期的销售员拥有一般销售员的全部权限但是不能有确定价格权限，这个时候需要“权限收缩”，如果太依赖于角色，需要新设一个新销售人员角色，再将其赋予给新入职的销售人员，灵活度不够。"&gt;同样的道理，假如我们希望新入职未过试用期的销售员拥有一般销售员的全部权限但是不能有确定价格权限，这个时候需要“权限收缩”，如果太依赖于角色，需要新设一个新销售人员角色，再将其赋予给新入职的销售人员，灵活度不够。&lt;/h4&gt;
&lt;p&gt;基于上述情况，考虑到“权利标签”的权限设置方式，以“权限”为是视野和最小颗粒度，当做一个个标贴，贴给谁，谁就有权限，撕掉标签，就丧失权利，初步设想如下：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;many_tags&lt;/span&gt;&lt;span class="err"&gt;：&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;candoA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;candoB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;candoC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;candoD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;candoE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;candoF&lt;/span&gt;&lt;span class="o"&gt;....&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="no"&gt;Permisson1_tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;candoA&lt;/span&gt;
&lt;span class="no"&gt;Permisson2_tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;candoB&lt;/span&gt;
&lt;span class="no"&gt;Permisson3_tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;candoA&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="no"&gt;B&lt;/span&gt;
 &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;permission1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;permission2&lt;/span&gt;

&lt;span class="no"&gt;Super_permisson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;candoALL&lt;/span&gt;
&lt;span class="no"&gt;Manager_role&lt;/span&gt;&lt;span class="sb"&gt;`s permission = cando A + cando B + Cando C
Teacher_role`&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;permission&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="no"&gt;Professor_role&lt;/span&gt;&lt;span class="sb"&gt;`s permission - candoB （教师角色权限为：教授角色的权限标签中去掉权限“candoB”）
=  cando M + cando N + Cando L（另一种表达：教师角色权限为能做M + N +L）

某一个教师需要临时增加阅卷权限
TeacherA`&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;permisson_in_24_hour&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;TeacherA&lt;/span&gt;&lt;span class="sb"&gt;`s current permisson + cando R(阅卷标签）

建立儿童教师组的权限：
Children_teacher_group`&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;permission&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;candoA&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="no"&gt;B&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="no"&gt;C&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="no"&gt;D&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="no"&gt;X&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="no"&gt;Y&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="no"&gt;M&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="no"&gt;P&lt;/span&gt;
        &lt;span class="n"&gt;或者另一种表达&lt;/span&gt;                            &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Manager_role&lt;/span&gt;&lt;span class="sb"&gt;`s permission - candoQ - candoR

将某一个具体的用户临时纳入儿童教师组
push_zhangsan_to_Children_teacher_group_in_20_days
在20天内，张三获得儿童教师组的全部权限

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="将某一类角色纳入儿童教师组"&gt;将某一类角色纳入儿童教师组&lt;/h4&gt;&lt;h4 id="RoleA_turned_into_Children_teacher_group_member_in_365_days（角色A自动在长期譬如365天内获得儿童教组的全部权限，并且该类角色在儿童教师组的权限增长、削减时，同步削减，如果某一个教师，拥有roleA，则相应的获得教师角色的全部权限，并且随着roleA的权限同步变动，同时该教师还可以通过增加临时权限标签的方式，取得roleA之外的临时权限）"&gt;RoleA_turned_into_Children_teacher_group_member_in_365_days（角色 A 自动在长期譬如 365 天内获得儿童教组的全部权限，并且该类角色在儿童教师组的权限增长、削减时，同步削减，如果某一个教师，拥有 roleA，则相应的获得教师角色的全部权限，并且随着 roleA 的权限同步变动，同时该教师还可以通过增加临时权限标签的方式，取得 roleA 之外的临时权限）&lt;/h4&gt;
&lt;p&gt;以上是初步思考，很多不成熟之处，供探讨。&lt;/p&gt;</description>
      <author>y9info</author>
      <pubDate>Sat, 24 Feb 2024 11:23:41 +0800</pubDate>
      <link>https://ruby-china.org/topics/43597</link>
      <guid>https://ruby-china.org/topics/43597</guid>
    </item>
    <item>
      <title>Ruby 语言为例，从一个想法到一个完成（不一定要求完美）的应用程序，应当遵循怎样的流程和规范？</title>
      <description>&lt;p&gt;我是一个已经入门了一定年限的新手，非专业的，目前已经作出了一些小的程序（譬如爬虫、工作上的管理系统等），也会写一些代码，还能跑起来，对 HTML、CSS、JavaScript 也有一定的了解，也看过元编程、面向对象等书籍，感觉有一定朦胧的理解和感悟，但是发现这样一个问题：每当我有一个想法，想做一个稍微大一点、复杂一点的应用，就会发现非常茫然和混沌，写着写着就感觉自己是在瞎写，这种瞎写体现在对象的构建、架构的规划、文档的整理等等，通常是想法很美好，落地很悲惨。&lt;/p&gt;

&lt;p&gt;举个例子，例如我想做一个围棋程序，棋盘、棋子静态的都画出来了，按照我的想法，可能要有“棋盘”、“棋子”、“棋手”、“裁判”、“记录”、“规则”等对象，但是下一步，怎么把这些对象串联起来，怎么样让他们之间互相能相互交流、传达指令（方法），能成为一个整体并进而“活”起来，却感觉很为难，不知道怎么去统筹规划。&lt;/p&gt;

&lt;p&gt;不知道大家是怎么看待这个问题？是怎么突破想法（需求）和形成应用软件的之间的这个“鸿沟”的？怎么样的整体的去考虑，而不是一点一点的添灯油、打补丁，想到哪儿写到哪儿，写到哪儿算哪儿这种问题？&lt;/p&gt;

&lt;p&gt;希望各位大佬、过来人能给一些指点迷津，指一些方向。&lt;/p&gt;</description>
      <author>y9info</author>
      <pubDate>Sat, 10 Jun 2023 10:59:26 +0800</pubDate>
      <link>https://ruby-china.org/topics/43163</link>
      <guid>https://ruby-china.org/topics/43163</guid>
    </item>
    <item>
      <title>怎样批量上传 avatar</title>
      <description>&lt;p&gt;已经通过 Active Storage、user.avatar.attach(params[:avatar]) 方式建立了单个 avatar 的上传页面，功能正常。现在假如有 1000 个小学生的图像 avatar 需要上传对应这 1000 个小学生，并且这些图像都命名为 name_id.jpg，能够根据图像找到 user（已经建立了图片和对象的关系），现在不想从前端页面一个一个的上传 avata，有没批量的方法上传这 1000 个图像？想通过 rails seed，或者 RestClient，或 net/http，摸索了很久。&lt;/p&gt;</description>
      <author>y9info</author>
      <pubDate>Thu, 30 Mar 2023 11:24:17 +0800</pubDate>
      <link>https://ruby-china.org/topics/42972</link>
      <guid>https://ruby-china.org/topics/42972</guid>
    </item>
    <item>
      <title>rails7 CSS 的设置</title>
      <description>&lt;p&gt;rails 对前端的有所改动，记录一下 rails7 中 css 的设置&lt;/p&gt;
&lt;h3 id="一、创建项目时，直接做好css规划，例如设置bootstrap 作为css："&gt;一、创建项目时，直接做好 css 规划，例如设置 bootstrap 作为 css：&lt;/h3&gt;
&lt;p&gt;命令行窗口输入&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;rails&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;blog&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="n"&gt;esbuild&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;css&lt;/span&gt; &lt;span class="n"&gt;bootstrap&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;database&lt;/span&gt; &lt;span class="n"&gt;postgresql&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="二、使用自己写的，或其他途径粘贴的css内容"&gt;二、使用自己写的，或其他途径粘贴的 css 内容&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;在 app/assets/stylesheets 创建一个名为 my.css 文件；&lt;/li&gt;
&lt;li&gt;在 app/assets/config/manifest.js 文件内容的末尾，单独增加一行“//= link my.css”&lt;/li&gt;
&lt;li&gt;在 app/views/layouts/application.html.erb 这个文件的 stylesheet_link_tag 中，增加“my",增加后变为：&lt;/li&gt;
&lt;/ol&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;stylesheet_link_tag&lt;/span&gt; &lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;application&lt;/span&gt;&lt;span class="err"&gt;",&lt;/span&gt; &lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;my&lt;/span&gt;&lt;span class="err"&gt;",&lt;/span&gt; &lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;data-turbo-track&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;:&lt;/span&gt; &lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;reload&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;/code&gt;&lt;/pre&gt;</description>
      <author>y9info</author>
      <pubDate>Fri, 10 Feb 2023 22:43:01 +0800</pubDate>
      <link>https://ruby-china.org/topics/42868</link>
      <guid>https://ruby-china.org/topics/42868</guid>
    </item>
    <item>
      <title>Stimulus 安装出现 Command failed with exit code 1.错误处理</title>
      <description>&lt;p&gt;按照 Stimulus 手册，安装步骤是：&lt;/p&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;git clone https://github.com/hotwired/stimulus-starter.git
$ cd stimulus-starter
$ yarn install
$ yarn start
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;运行最后一步 yarn start 出现如下错误：&lt;/p&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;Node.js v18.12.1
error Command failed with exit code 1.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;是 Node.js 版本太高，重新安装 v12 版本即可：&lt;/p&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;nvm install 12
nvm use 12.22.12
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;重新执行：&lt;/p&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;$ yarn install
$ yarn start
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;问题解决。&lt;/p&gt;</description>
      <author>y9info</author>
      <pubDate>Fri, 23 Dec 2022 00:46:27 +0800</pubDate>
      <link>https://ruby-china.org/topics/42803</link>
      <guid>https://ruby-china.org/topics/42803</guid>
    </item>
    <item>
      <title>求助：怎样将搜狗词库 scel 格式文件转为 txt？</title>
      <description>&lt;p&gt;目前了解的情况：
1.根据查找的信息，搜狗的 scel 词库就是保存的文本的 unicode 编码，每两个字节一个字符（中文汉字或者英文字母）
2.初步编码如下：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"C:/Users/Administrator/Desktop/test/搜狗词汇.scel"&lt;/span&gt;
&lt;span class="n"&gt;source_file&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;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"rb"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
    &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;source_file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sysread&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="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt;
    &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
        &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;message&lt;/span&gt;
        &lt;span class="k"&gt;break&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;source_file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;3.上述 2 代码运行显示的结果为：
"a\x00"
"\xEE\x00"
"\x06\x00"
"p\x00"
"a\x00"
"i\x00"
"\xEF\x00"
"\x06\x00"
"p\x00"
"a\x00"
"n\x00"
"\xF0\x00"
"\b\x00"
"p\x00"
"a\x00"
"n\x00"
"g\x00"
"\xF1\x00"
"\x06\x00"
"p\x00"
"a\x00"
"o\x00"
"\xF2\x00"
"\x06\x00"
怎样将上述转码成 txt 文本呢？或者说怎样将上述的字节码转为字符串呢？&lt;/p&gt;</description>
      <author>y9info</author>
      <pubDate>Fri, 15 Jul 2022 20:41:47 +0800</pubDate>
      <link>https://ruby-china.org/topics/42519</link>
      <guid>https://ruby-china.org/topics/42519</guid>
    </item>
    <item>
      <title>自学笔记专区—005 将路由包装在块中，解决“uncaught throw :warden devise”错误</title>
      <description>&lt;h3 id="问题描述："&gt;问题描述：&lt;/h3&gt;
&lt;p&gt;一般而言，使用 gem devise 进行用户认证时，在控制器中，增加一句“before_action :authenticate_user!”就可以实现目的。但是当控制器中存在模块引用“include ActionController::Live”时，会抛出“uncaught throw :warden devise”错误，去掉该模块引用“include ActionController::Live”，该错误消失。&lt;/p&gt;

&lt;p&gt;###问题解决：
经过谷歌查询，得到的解决方案是，将路由包装在块中，解决“uncaught throw :warden devise”错误，即：
之前路由：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:docfiles&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;collection&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;delete&lt;/span&gt; &lt;span class="ss"&gt;:destroy_files&lt;/span&gt;
        &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="ss"&gt;:download_files&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="n"&gt;member&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;delete&lt;/span&gt; &lt;span class="s1"&gt;'/files/:file_id'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'docfiles#destroy_file'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;as: :destroy_file&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;将路由包装在块中后的路由：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;authenticate&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:docfiles&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;collection&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;delete&lt;/span&gt; &lt;span class="ss"&gt;:destroy_files&lt;/span&gt;
        &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="ss"&gt;:download_files&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="n"&gt;member&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;delete&lt;/span&gt; &lt;span class="s1"&gt;'/files/:file_id'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'docfiles#destroy_file'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;as: :destroy_file&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;/code&gt;&lt;/pre&gt;
&lt;p&gt;通过以上方案，问题解决。
具体参见：&lt;a href="https://github.com/heartcombo/devise/issues/2332" rel="nofollow" target="_blank"&gt;https://github.com/heartcombo/devise/issues/2332&lt;/a&gt;&lt;/p&gt;</description>
      <author>y9info</author>
      <pubDate>Wed, 16 Feb 2022 11:09:53 +0800</pubDate>
      <link>https://ruby-china.org/topics/42143</link>
      <guid>https://ruby-china.org/topics/42143</guid>
    </item>
    <item>
      <title>自学笔记专区—004 active storage 判断是否是否是新上传的文件</title>
      <description>&lt;h3 id="问题提出："&gt;问题提出：&lt;/h3&gt;
&lt;p&gt;在使用 active storage 上传文件后，难免要对上传的文件进行后续的管理，譬如重命名，譬如归类，譬如增加标识等等，但是文件上传后，从文件列表中，怎么判断这个文件是新上传的文件呢？&lt;/p&gt;
&lt;h3 id="问题解决："&gt;问题解决：&lt;/h3&gt;
&lt;p&gt;经过查询 api，发觉 new_record？方法并不适合，但是 rails 提供了一个非常对应的方法 previously_new_record？完美解决了这个问题，如果此对象刚刚创建，则返回 true，也就是说，在上次保存之前，该对象在数据库中不存在，会返回真。&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@todo_item.update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;todo_item_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
   &lt;span class="vi"&gt;@todo_item.files.each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;file&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;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;previously_new_record?&lt;/span&gt; 
      &lt;span class="vi"&gt;@new_files&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;file&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;</description>
      <author>y9info</author>
      <pubDate>Mon, 10 Jan 2022 11:17:04 +0800</pubDate>
      <link>https://ruby-china.org/topics/42065</link>
      <guid>https://ruby-china.org/topics/42065</guid>
    </item>
    <item>
      <title>自学笔记专区—003 check_box 单选框作为拨动（toggle）功能按钮的问题（rails ujs 功能使用）</title>
      <description>&lt;h3 id="问题描述："&gt;问题描述：&lt;/h3&gt;
&lt;p&gt;在不少场景下，需要一个拨动功能（toggle）的按钮，譬如在 todolist 中，勾选中，即代表任务“完成”；对已经勾选中的任务，取消勾选，则代表任务恢复为为“未完成”的状态。
还有其他类似是否缴费、是否已发送提醒以及很多二选一状态的功能设置都需要拨动功能设置。
就上述，需要一个简单的解决方案。&lt;/p&gt;
&lt;h3 id="解决方案："&gt;解决方案：&lt;/h3&gt;
&lt;p&gt;model：
在模型属性层面，需要一个类似二选一的属性，譬如 todo.status  或者 task.completed?&lt;/p&gt;

&lt;p&gt;view：
在前端，需要一个简单的方案，下拉选框，通常使用 link_to 可以很方便的解决点击不同下拉选项进行不同操作的问题。而对于拨动功能按钮，最简单的方案是 单选框。
前端代码如下：&lt;/p&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"check_completed_&amp;lt;%= todo_item.id %&amp;gt;"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="na"&gt;data-remote=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;data-url=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;%= toggle_todolist_path(todo_item) %&amp;gt;"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt; &lt;span class="na"&gt;data-method=&lt;/span&gt;&lt;span class="s"&gt;"post"&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&amp;lt;i&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"fas fa-check"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/i&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;以上是未选中状态的代码，选中状态下的的前端如下：&lt;/p&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"check_completed_&amp;lt;%= todo_item.id %&amp;gt;"&lt;/span&gt; &lt;span class="na"&gt;checked&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="na"&gt;data-remote=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;data-url=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;%= completed_todolist_path(todo_item) %&amp;gt;"&lt;/span&gt;  &lt;span class="na"&gt;data-method=&lt;/span&gt;&lt;span class="s"&gt;"post"&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&amp;lt;i&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"fas fa-check"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/i&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;未选中状态的前端代码，少了 value，多了 checked。后端控制器主要是通过 value 的值判断前端选中或未选中的状态。&lt;/p&gt;

&lt;p&gt;routes（路由设置）：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:todolists&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;member&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="s2"&gt;"toggle"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"todolists#toggle"&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;在路由中，设置一个拨动 toggle 的路由，对应的控制器方法是 toggle&lt;/p&gt;

&lt;p&gt;controller：
控制器读取前端的 input 的 value 值，并根据 value 改变模型的属性值。&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;toggle&lt;/span&gt;
    &lt;span class="vi"&gt;@todo_item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Todolist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="n"&gt;input_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"check_completed_"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="vi"&gt;@todo_item.id.to_s&lt;/span&gt;     &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="sr"&gt;/ input_name即前端单选框的名字，对应的前端代码 input name="check_completed_&amp;lt;%= todo_item.id %&amp;gt;" 

    if  params[input_name] == "1"
      @todo_item.update_attribute(:status, 'completed')
      redirect_to todolists_path
    else
      @todo_item.update_attribute(:status, 'uncompleted')
      redirect_to todolists_path
    end

  end
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="总结"&gt;总结&lt;/h3&gt;
&lt;p&gt;上述解决方案，前端通过 data-remote  data-url data-method 的 Unobtrusive JavaScript 的远程元素方法，即 rails ujs 方法，实现了 input 一行代码将前端设置传递到后端控制器，简便便捷。
相关资源网址：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;a href="https://guides.rubyonrails.org/working_with_javascript_in_rails.html" rel="nofollow" target="_blank"&gt;https://guides.rubyonrails.org/working_with_javascript_in_rails.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; &lt;a href="https://github.com/rails/jquery-ujs/wiki/Unobtrusive-scripting-support-for-jQuery-list-of-data-attributes)" rel="nofollow" target="_blank"&gt;https://github.com/rails/jquery-ujs/wiki/Unobtrusive-scripting-support-for-jQuery-list-of-data-attributes)&lt;/a&gt;(&lt;/li&gt;
&lt;/ol&gt;</description>
      <author>y9info</author>
      <pubDate>Tue, 28 Dec 2021 12:30:36 +0800</pubDate>
      <link>https://ruby-china.org/topics/42036</link>
      <guid>https://ruby-china.org/topics/42036</guid>
    </item>
    <item>
      <title>自学笔记专区—002 限制上传的文件类型</title>
      <description>&lt;h3 id="问题描述："&gt;问题描述：&lt;/h3&gt;
&lt;p&gt;前端使用 form 上传文件，要求限定上传的格式为图片。
改进前使用 accept:来限制文件类型，但是发觉这种限制比较弱，用户选择其他格式文件后，仍然可以提交非图片格式的文件到后端。&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sx"&gt;%= form.file_field :tm_image,&amp;nbsp;multiple:false,class:"form-control ",style:"width:300px;",&amp;nbsp;accept:'image/png,image/gif,image/jpeg,image/jpg,image/tiff,image/bmp,image/svg' %&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="解决方案："&gt;解决方案：&lt;/h3&gt;
&lt;p&gt;解决方案分两个小点，一个是读取用户选取的文件的文件格式并判断是否图片格式，另一个是，在非图片文件格式时，提示用户。&lt;/p&gt;
&lt;h4 id="1. JavaScript代码如下"&gt;1. JavaScript 代码如下&lt;/h4&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text/javascript&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;checkImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;)&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;realFileElement&lt;/span&gt; &lt;span class="o"&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;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#realFileType&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;      &lt;span class="c1"&gt;//这里的realFileElement元素，对应为上述form中的input框下面为提示建立的div&lt;/span&gt;
              &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;files&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="c1"&gt;///读取用户选取的文件&lt;/span&gt;
              &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;filePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;img&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="c1"&gt;///读取用户选取的文件的路径&lt;/span&gt;
              &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;fileExt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lastIndexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.&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="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;///截取用户选取的文件的后缀名&lt;/span&gt;

              &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;checkFileExt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileExt&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;          &lt;span class="c1"&gt;///如果文件后缀名检测不是图片 &lt;/span&gt;
                  &lt;span class="nx"&gt;realFileElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`所选“&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;file&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="s2"&gt;”文件不是图片,请选择图片！`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;///innerText 方法，在提示div区域写入提示内容&lt;/span&gt;
                  &lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;///同时将input框的value设置为空，因为文件后缀名不是图片&lt;/span&gt;
                  &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
              &lt;span class="p"&gt;}&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;checkFileExt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;            &lt;span class="c1"&gt;///检测后缀名是否为图片格式的函数&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/.jpg|.gif|.png|.bmp|.jpeg|.tiff|.svg/i&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="kc"&gt;true&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="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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="2.将函数嵌入form，在file input中增加:onchange ，变更后的form如下："&gt;2.将函数嵌入 form，在 file input 中增加:onchange，变更后的 form 如下：&lt;/h4&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sx"&gt;%= form.file_field :tm_image,&amp;nbsp;multiple:false,class:"form-control ",style:"width:300px;",&amp;nbsp;accept:'image/png,image/gif,image/jpeg,image/jpg,image/tiff,image/bmp,image/svg',:onchange =&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"checkImage(this)"&lt;/span&gt; &lt;span class="o"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="3.在input框下面增加提示的div"&gt;3.在 input 框下面增加提示的 div&lt;/h4&gt;
&lt;p&gt;///通过其他方式提示也可以，譬如 alert，但 alert 提示个人感觉，用户处理时需要移动眼球和鼠标，不如这种提示方法感知度好。&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;"text-red"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"realFileType"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;   ///这里的 id="realFileType"，对应的是上述JavaScript函数中的 const realFileElement = document.querySelector("#realFileType"); 
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="说明"&gt;说明&lt;/h3&gt;
&lt;p&gt;上述 JavaScript 函数通过读取用户选取的文件的后缀名来判断文件类型，存在一定的不足，譬如可以通过修改虚假的文件名后缀来骗过上述函数，用户可以手动修改文件后缀名以绕过格式限制，从而上传成功。上述方案的优点是，代码简单，不需要了解太高深的文件类型二进制数据判断知识，JavaScript 小白也能读懂，一般场景下对文件类型校验没有太高要求的，应用也基本足够。
更完善的解决方法是，读取文件二进制数据中的文件签名来精准判断文件类型，详见&lt;a href="https://github.com/jealyn/real-file-type" rel="nofollow" target="_blank"&gt;https://github.com/jealyn/real-file-type&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;上述方法，稍作改动也可以用于判断 docx、pdf 等格式，也能增加文件大小的判断，需要增加代码也不多。&lt;/p&gt;</description>
      <author>y9info</author>
      <pubDate>Tue, 14 Dec 2021 13:56:24 +0800</pubDate>
      <link>https://ruby-china.org/topics/41982</link>
      <guid>https://ruby-china.org/topics/41982</guid>
    </item>
    <item>
      <title>求助：同音的属性名称查询以及类似需要对属性进行转化后对比的查询处理</title>
      <description>&lt;p&gt;有一个商标表，包括商标名称（名称统一都是汉字）、商标号码等等，现在需求是：在用户输入一个商标名称时，可以查询同名、同音的商标。
例如：输入查询商标名称“华为”，查询结果可以显示出“华为”、“化为”、“华威”、“华微”、"花薇”等等同名、同音的商标。&lt;/p&gt;

&lt;p&gt;目前考虑解决办法是，在商标表中，增加一列 pinyin 名称，在创建商标时，自动生成一列拼音的名称属性“name_pinyin"存储名称的汉语拼音，再创建组合查询如下 ,但是考虑这种增加仅仅为方便查询所用增加列，感觉不美，不知道有没有更简洁的查询处理方法？&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;search_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;trademarks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"name like ? or name_pinyin like ?"&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="no"&gt;Pinyin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;t&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;/code&gt;&lt;/pre&gt;
&lt;p&gt;从上面的问题衍生出来一个问题：如果对象属性列中，包含一个属性，但是需要对该属性进行必要的转化、清洗后才能对比查询的的简洁处理方法是？&lt;/p&gt;

&lt;p&gt;譬如：一张学生列表，只保存了姓名、身份证号，班级等等，没有性别这一列（按照表尽量简单的原则，身份证号码可以查询性别、出生日期就没单独增加性别、出生日期的属性），现在要通过身份证号码查出性别为男生、出生月份为 9 月的学生（仅做举例，所以表尽可能设置的简单，没有出生年月和性别的列，需要从身份证中推导）。
如果不增加列，简洁的处理方法是？&lt;/p&gt;</description>
      <author>y9info</author>
      <pubDate>Mon, 13 Dec 2021 12:51:24 +0800</pubDate>
      <link>https://ruby-china.org/topics/41974</link>
      <guid>https://ruby-china.org/topics/41974</guid>
    </item>
    <item>
      <title>自学笔记专区—001</title>
      <description>&lt;h3 id="问题描述："&gt;问题描述：&lt;/h3&gt;
&lt;p&gt;rails 前端通常有很多列表，譬如 books 的 index 页面，查询后的显示结果页面等等，都有多个实例，如果要从多个实例中选取一部分实例，提交到后台进行进一步的处理，譬如提交到后台进行删除、作为附件转发等等，就会利用 check_box 从前端选取实例，这个时候要把 check_box 的 value 值的集合，作为参数，通过 form 提交到后端，让后端的 controller 读取。
通常的做法是利用 form 包裹参数，通过 form 的 submit 提交，在 form_tag 中指明提交的路径、method 等等。这个时候就有一个问题：
如果选取的实例，有时候是提交到后台删除，有时候是提交到后台作为附件转发，有时候是提交到后台批量下载，每个 form 对应的路径、method 等相关内容都不相同，难道要使用多个 form_tag？而且 form_tag 的 submit 按钮通常在底部，如果要把按钮设置在 form 外面，譬如页面顶部，这样也存在一些页面处理问题。&lt;/p&gt;

&lt;p&gt;总之，处理不好会导致前端结构混乱，能否实现实例选取功能和提交功能分开，不同的 button 按钮，自动提交到不同的后台处理？&lt;/p&gt;
&lt;h3 id="解决方案："&gt;解决方案：&lt;/h3&gt;
&lt;p&gt;搜索了很多的解决方案，包括 button_to 等都不理想，解决一个 form_tag 提交还好说，一个页面解决多个提交，就会出现页面处理混乱。
最终决定用 JavaScript 来解决，思路是：使用 JavaScript 读取页面所有的 check_box 的 value，如果不为空，就存在一个数组里边，然后将该数组作为参数，由不同的 form_tag 提交。&lt;/p&gt;
&lt;h4 id="读取check_box的value并实现form提交的代码"&gt;读取 check_box 的 value 并实现 form 提交的代码&lt;/h4&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;submitform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;form_name&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
   &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&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;getElementsByName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;patent[files][]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="c1"&gt;//check_box被命名为了"patent[files][]"&lt;/span&gt;
   &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;check_val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;//判断复选框是否被选中&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="c1"&gt;//获取被选中的复选框的值&lt;/span&gt;
            &lt;span class="nx"&gt;check_val&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;k&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;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;files_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;check_val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;//将files_id在form中设置一个不显示的input数据，其value值设置为使用JavaScript读取页面所有的check_box的value的数组集合值，该值随着form提交&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;getElementsByName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;form_name&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;submit&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="c1"&gt;//为什么不用form_id来查找元素？因为form_tag中的form的id的值，用JavaScript不好读取，存在一个rails变量和JavaScript变量相互读取的难题&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="新建一个form，专门用于指明提交的路线，方法，该form不设置submit按钮（这样的form可以根据需要建很多个，对在前端页面的位置也没有太高的要求）"&gt;新建一个 form，专门用于指明提交的路线，方法，该 form 不设置 submit 按钮（这样的 form 可以根据需要建很多个，对在前端页面的位置也没有太高的要求）&lt;/h4&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sx"&gt;%= form_for(@patent, url: destroy_files_patent_path(@patent), html: { name: "destroy_files_submit", method: "delete",}) do |form| %&amp;gt;
 &amp;lt;input type=&lt;/span&gt;&lt;span class="s2"&gt;"hidden"&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"files_id"&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"files_id"&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;  &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;    
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sx"&gt;% end &lt;/span&gt;&lt;span class="o"&gt;%&amp;gt;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="新建一个button，专门用于提交"&gt;新建一个 button，专门用于提交&lt;/h4&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;onclick=&lt;/span&gt;&lt;span class="s"&gt;"submitform('destroy_files_submit')"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn btn-outline-secondary"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;删除选中&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
//onclick= 用于执行submitform这个函数
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="小结"&gt;小结&lt;/h4&gt;
&lt;p&gt;通过上述处理，用 JavaScript 函数来读取 check_box 参数值给到 form_tag 用于提交（其实也可以根据需要，通过调整 document.getElementById，调整为读取其他的前端页面所需要的值），然后再根据需要传递到后端，解决了 form_tag 与前端页面部分太过于深度耦合的问题，灵活性大大增加。从此打通前后端参数搜集传递的任督二脉，浑身舒爽，而涉及到的 JavaScript 代码并不多，难度也能理解，甚至在 JavaScript 代码中也能进一步增加参数的校验功能。&lt;/p&gt;

&lt;p&gt;以上是几天来的摸索结果，以为记。&lt;/p&gt;</description>
      <author>y9info</author>
      <pubDate>Thu, 25 Nov 2021 12:18:05 +0800</pubDate>
      <link>https://ruby-china.org/topics/41923</link>
      <guid>https://ruby-china.org/topics/41923</guid>
    </item>
  </channel>
</rss>
