<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>brooke (ops)</title>
    <link>https://ruby-china.org/brooke</link>
    <description/>
    <language>en-us</language>
    <item>
      <title>（零基础向）Ruby on Rails 从零搭建一个 Blog</title>
      <description>&lt;h2 id="重点概念"&gt;重点概念&lt;/h2&gt;&lt;h3 id="MVC"&gt;MVC&lt;/h3&gt;
&lt;p&gt;首先得了解 MVC 是什么东西，即 M(Model，模型)V(View，视图)C(Controller，控制器)。接下来从一个完整的 Ruby on Rails(ror) 项目流程来了解三者之间的关系。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;请求到达控制器&lt;/strong&gt;：用户发送 HTTP 请求，请求被路由系统分发给相应的控制器动作。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;控制器处理请求&lt;/strong&gt;：控制器接收请求，可能会从模型中获取数据，或者对模型进行操作。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;数据传递给视图&lt;/strong&gt;：控制器通过实例变量将获取到的数据传递给视图。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;视图渲染响应&lt;/strong&gt;：视图使用嵌入 Ruby 代码的 ERB 模板，将控制器传递的数据渲染成最终的 HTML 响应。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;响应返回给用户&lt;/strong&gt;：最终生成的 HTML 响应由 Rails 框架发送给用户的浏览器，用户在浏览器中看到相应的页面或者数据。&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;由上面可知，模型负责和数据库做对接操作，控制器则负责从模型当中获取需要数据，视图则是负责对拿到的数据进行渲染。&lt;/p&gt;
&lt;h3 id="Console"&gt;Console&lt;/h3&gt;
&lt;p&gt;在 Ruby on Rails 中，console（控制台）指的是一个命令行工具，通常称为 Rails 控制台或 Rails 命令行控制台。它提供了一个交互式的环境，允许开发者在不启动完整的 Rails 应用程序的情况下，执行 Ruby 代码和与应用程序进行交互。&lt;/p&gt;
&lt;h2 id="项目常用命令"&gt;项目常用命令&lt;/h2&gt;&lt;h3 id="创建一个新的ror项目"&gt;创建一个新的 ror 项目&lt;/h3&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails new &amp;lt;PROJECT-NAME&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="开启新的服务"&gt;开启新的服务&lt;/h3&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bin/rails server
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails server
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="创建controller"&gt;创建 controller&lt;/h3&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bin/rails generate controller &amp;lt;CONTROLLER-NAME&amp;gt; index --skip-routes
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="创建model"&gt;创建 model&lt;/h3&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bin/rails generate model &amp;lt;MODEL-NAME&amp;gt; &amp;lt;DB-FIELD&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="和console进行交互"&gt;和 console 进行交互&lt;/h3&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bin/rails console
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="Blog项目实践"&gt;Blog 项目实践&lt;/h2&gt;
&lt;p&gt;首先运行&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails new blog
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;来创建一个名为 &lt;code&gt;blog&lt;/code&gt; 的 ror 项目，接下去进入到 blog 目录 &lt;code&gt;cd blog&lt;/code&gt; 。如果成功的话，运行 &lt;code&gt;bin/rails server&lt;/code&gt; 之后，就可以访问到 &lt;code&gt;http://localhost:3000/&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;博客文章至少需要两个部分的内容一个是标题 &lt;code&gt;title&lt;/code&gt; 还有内容主题 &lt;code&gt;body&lt;/code&gt; 。我们来创建有这两个部分的 &lt;code&gt;model&lt;/code&gt; , 运行 &lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bin/rails generate model Article title:string body:text
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;将创建一个 &lt;code&gt;migrate文件&lt;/code&gt; ，在 &lt;code&gt;/db/migrate&lt;/code&gt; 下面。这个文件里的内容为&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 定义了一个名为 CreateArticles 的 Ruby 类，它继承自 ActiveRecord::Migration[7.1]。在 Rails 中，迁移类用于修改数据库结构，继承自 ActiveRecord::Migration 提供了一系列用于定义数据库迁移的方法和规范&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CreateArticles&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Migration&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;7.1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="c1"&gt;# change 方法是 ActiveRecord::Migration 提供的一个特殊方法，用于定义要执行的数据库操作。在这个迁移中，change 方法内部包含了创建名为 articles 的新表格的指令&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;change&lt;/span&gt;
        &lt;span class="c1"&gt;# create_table 是 ActiveRecord::Migration 提供的方法之一，用于在数据库中创建新的表格。在这里，我们创建了一个名为 articles 的表格，do |t| 部分是一个代码块，用于定义表格的各个列和其属性&lt;/span&gt;
        &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="ss"&gt;:articles&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;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
            &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="ss"&gt;:title&lt;/span&gt;
            &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt; &lt;span class="ss"&gt;:body&lt;/span&gt;

            &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timestamps&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;code&gt;articles&lt;/code&gt; 的数据库表格，该表格具有 &lt;code&gt;title&lt;/code&gt;（字符串类型）和 &lt;code&gt;body&lt;/code&gt;（文本类型）两列，以及自动生成的 &lt;code&gt;timestamps&lt;/code&gt; 列（用于记录创建和更新时间）。&lt;/p&gt;

&lt;p&gt;博客项目肯定需要有增删改查操作，即增加文章，删除文章，修改文章，查找文章。将这四个功能写入到 &lt;code&gt;app/controllers/articles_controller.rb&lt;/code&gt; 当中，就是&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 这行代码的核心作用是定义一个名为 ArticlesController 的控制器类，并使其继承自 ApplicationController，以便在 Rails 应用中处理和管理与文章相关的逻辑和请求&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ArticlesController&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="c1"&gt;# 获取所有文章并将它们存储在实例变量 @articles 中，以便在视图中显示所有文章列表&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt; 
        &lt;span class="vi"&gt;@articles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="c1"&gt;# 根据传入的 params[:id] 查找特定 ID 的文章，并将其存储在实例变量 `@article` 中，以便在显示单个文章的视图中使用&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;@article&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="c1"&gt;# 创建一个新的空白文章对象 `@article`，用于在创建新文章的表单页面中使用&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;
        &lt;span class="vi"&gt;@article&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="c1"&gt;# 根据从表单收集的 article_params 创建新的文章对象，并尝试保存到数据库。如果保存成功，重定向到新创建的文章页面；如果保存失败，则重新渲染创建文章的表单页面，并返回状态码 422 Unprocessable Entity&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;
        &lt;span class="vi"&gt;@article&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Article&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;article_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@article.save&lt;/span&gt;
            &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="vi"&gt;@article&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:new&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="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="c1"&gt;# 根据传入的 params[:id] 查找要编辑的文章，并将其存储在实例变量 `@article` 中，以便在编辑文章的表单页面中使用&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;edit&lt;/span&gt;
        &lt;span class="vi"&gt;@article&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="c1"&gt;# 根据传入的 params[:id] 查找要更新的文章，并根据从表单收集的 article_params 尝试更新。如果更新成功，则重定向到更新后的文章页面；如果更新失败，则重新渲染编辑文章的表单页面，并返回状态码 422 Unprocessable Entity&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;
        &lt;span class="vi"&gt;@article&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@article.update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="vi"&gt;@article&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:edit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;status: :unprocessable_entity&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;# 根据传入的 params[:id] 查找要删除的文章，并将其从数据库中删除。完成后重定向到根路径 (root_path)，并返回状态码 303 See Other&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;destroy&lt;/span&gt;
        &lt;span class="vi"&gt;@article&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Article&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="vi"&gt;@article.destroy&lt;/span&gt;

        &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;root_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;status: :see_other&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="c1"&gt;# 定义了一个私有方法 article_params，用于过滤和允许 params 中的 article 参数，防止不必要的数据传递和安全问题&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;article_params&lt;/span&gt;
        &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:article&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;permit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;接下来就是视图部分，视图有四个文件 &lt;code&gt;edit.html.erb&lt;/code&gt;, &lt;code&gt;index.html.erb&lt;/code&gt;, &lt;code&gt;new.html.erb&lt;/code&gt;, &lt;code&gt;show.html.erb&lt;/code&gt;, 分别对应着编辑页面，首页，新建页面，展示页面。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;edit.html.erb&lt;/code&gt; 用于编辑现有的文章。它预填充了现有文章的标题和正文内容，允许用户对这些内容进行修改，并提交表单以更新文章信息。&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;index.html.erb&lt;/code&gt; 用于展示文章列表和提供创建新文章的入口。&lt;/li&gt;
&lt;li&gt; &lt;code&gt;new.html.erb&lt;/code&gt; 用于创建新的文章。它包含了一个空的文章表单，用户可以填写标题和正文内容，并提交表单以创建新的文章。&lt;/li&gt;
&lt;li&gt; &lt;code&gt;show.html.erb&lt;/code&gt; 用于展示单篇文章的详细内容。它显示了文章的标题和正文，并提供了编辑和删除操作的链接。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;接下来我将展示这四个部分的代码&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# blog/models/views/articles/edit.html.erb
&amp;lt;h1&amp;gt;Edit Article&amp;lt;/h1&amp;gt;
# 使用 form_with 方法生成一个表单，该表单与 @article 实例相关联，表示该表单用于编辑现有的文章对象
&amp;lt;%= form_with model: @article do |form| %&amp;gt;

# 在表单中显示文章标题的输入字段。使用 form.label 和 form.text_field 方法分别生成标题字段的标签和文本输入框。如果 @article 的标题验证失败（例如长度限制等），则会显示相应的错误消息（通过@article.errors.full_messages_for(:title) 迭代输出每个错误消息）
&amp;lt;div&amp;gt;
&amp;lt;%= form.label :title %&amp;gt;&amp;lt;br&amp;gt;
&amp;lt;%= form.text_field :title %&amp;gt;
&amp;lt;% @article.errors.full_messages_for(:title).each do |message| %&amp;gt;
&amp;lt;div&amp;gt;&amp;lt;%= message %&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;% end %&amp;gt;
&amp;lt;/div&amp;gt;

# 在表单中显示文章正文的文本区域字段。类似于标题字段，使用 form.label 和 form.text_area 方法生成正文字段的标签和文本区域。如果 @article 的正文验证失败，将会显示相应的错误消息
&amp;lt;div&amp;gt;
&amp;lt;%= form.label :body %&amp;gt;&amp;lt;br&amp;gt;
&amp;lt;%= form.text_area :body %&amp;gt;&amp;lt;br&amp;gt;
&amp;lt;% @article.errors.full_messages_for(:body).each do |message| %&amp;gt;
&amp;lt;div&amp;gt;&amp;lt;%= message %&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;% end %&amp;gt;
&amp;lt;/div&amp;gt;

# 显示一个提交按钮，允许用户提交表单数据以更新文章的标题和正文内容
&amp;lt;div&amp;gt;
&amp;lt;%= form.submit %&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# blog/models/views/articles/index.html.erb

&amp;lt;h1&amp;gt;Articles&amp;lt;/h1&amp;gt;

# 使用 &amp;lt;ul&amp;gt; 和 &amp;lt;li&amp;gt; 标签显示文章的列表。通过 &amp;lt;% @articles.each do |article| %&amp;gt; 循环遍历 @articles 实例变量中的每篇文章对象，对于每篇文章，使用 link_to 方法生成一个链接，链接到文章的详情页面（article_path(article)），显示文章的标题 article.title
&amp;lt;ul&amp;gt;
&amp;lt;% @articles.each do |article| %&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;%= link_to article.title, article %&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;% end %&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;%= link_to "New Article", new_article_path %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# blog/models/views/articles/new.html.erb
&amp;lt;h1&amp;gt;New Article&amp;lt;/h1&amp;gt;

# 使用 `form_with` 方法生成一个表单，该表单与 `@article` 实例相关联，表示该表单用于创建一个新的文章对象
&amp;lt;%= form_with model: @article do |form| %&amp;gt;

# 在表单中显示文章标题的输入字段。使用 form.label 和 form.text_field 方法分别生成标题字段的标签和文本输入框。如果 @article 的标题验证失败（例如长度限制等），则会显示相应的错误消息（通过 @article.errors.full_messages_for(:title) 迭代输出每个错误消息）
&amp;lt;div&amp;gt;
&amp;lt;%= form.label :title %&amp;gt;&amp;lt;br&amp;gt;
&amp;lt;%= form.text_field :title %&amp;gt;
&amp;lt;% @article.errors.full_messages_for(:title).each do |message| %&amp;gt;
&amp;lt;div&amp;gt;&amp;lt;%= message %&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;% end %&amp;gt;
&amp;lt;/div&amp;gt;

# 在表单中显示文章正文的文本区域字段。类似于标题字段，使用 form.label 和 form.text_area 方法生成正文字段的标签和文本区域。如果 @article 的正文验证失败，将会显示相应的错误消息
&amp;lt;div&amp;gt;
&amp;lt;%= form.label :body %&amp;gt;&amp;lt;br&amp;gt;
&amp;lt;%= form.text_area :body %&amp;gt;&amp;lt;br&amp;gt;
&amp;lt;% @article.errors.full_messages_for(:body).each do |message| %&amp;gt;
&amp;lt;div&amp;gt;&amp;lt;%= message %&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;% end %&amp;gt;
&amp;lt;/div&amp;gt;

# 表单提交
&amp;lt;div&amp;gt;
&amp;lt;%= form.submit %&amp;gt;
&amp;lt;/div&amp;gt;

&amp;lt;% end %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# blog/models/views/articles/show.html.erb
&amp;lt;h1&amp;gt;&amp;lt;%= @article.title %&amp;gt;&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;%= @article.body %&amp;gt;&amp;lt;/p&amp;gt;
# 显示两个操作链接，一个是 "Edit" 编辑链接，另一个是 "Destroy" 删除链接
&amp;lt;ul&amp;gt;
# 使用 link_to 方法生成一个编辑链接，链接到编辑文章页面 (edit_article_path(@article))。用户点击这个链接可以进入编辑该文章的页面
&amp;lt;li&amp;gt;&amp;lt;%= link_to "Edit", edit_article_path(@article) %&amp;gt;&amp;lt;/li&amp;gt;
# 使用 link_to 方法生成一个删除链接，链接到删除文章的路由路径 (article_path(@article))。同时，使用 data 选项传递了 turbo_method: :delete 表示这是一个通过 Turbo 框架发送的删除请求，并提供了 turbo_confirm 提示用户确认删除操作
&amp;lt;li&amp;gt;&amp;lt;%= link_to "Destroy", article_path(@article), data: {
turbo_method: :delete,
turbo_confirm: "Are you sure?"
} %&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="反思"&gt;反思&lt;/h3&gt;
&lt;p&gt;当然这些代码还有很多不足，包括但不限于对于 &lt;code&gt;Controller&lt;/code&gt; 的 &lt;code&gt;destroy&lt;/code&gt; 部分，并没有添加如果操作失败的的错误打印等。&lt;/p&gt;</description>
      <author>brooke</author>
      <pubDate>Thu, 27 Jun 2024 03:36:08 +0800</pubDate>
      <link>https://ruby-china.org/topics/43767</link>
      <guid>https://ruby-china.org/topics/43767</guid>
    </item>
  </channel>
</rss>
