如何在Ubuntu 22.04上构建一个Ruby on Rails应用程序

引言

Rails是用Ruby编写的一个Web应用框架。它采用一种固执己见的开发方式,假设共同目标下,一套约定俗成的规则最适合开发者。因此,Rails提供了处理路由、有状态数据、资源管理等方面的约定,以提供大多数Web应用所需的基本功能。

Rails遵循模型-视图-控制器(MVC)的架构模式,该架构将应用程序逻辑(位于模型中)与路由和应用程序信息的呈现分离。这种组织结构以及允许开发人员将代码提取到助手和部分视图中的其他约定确保应用程序代码不会不必要地重复。

在这个教程中,您将构建一个Rails应用程序,让用户可以发布关于鲨鱼及其行为的信息。该项目将作为未来应用开发的起点。

先决条件

要按照这个教程进行操作,您需要:

  • A local machine or development server running Ubuntu 22.04. Your development machine should have a non-root user with administrative privileges and a firewall configured with ufw. For instructions on how to set this up, read our Initial Server Setup with Ubuntu 22.04 tutorial.
  • Node.js and npm installed on your local machine or development server. This tutorial uses Node.js version 18.13.0 and npm version 8.19.3. For guidance on installing Node.js and npm on Ubuntu 22.04, follow the instructions in the Option 2 —Installing Using a PPA section of How To Install Node.js on Ubuntu 22.04.
  • Ruby, rbenv, and Rails installed on your local machine or development server, following Steps 1-4 in How To Install Ruby on Rails with rbenv on Ubuntu 22.04. This tutorial uses Ruby 3.2.0, rbenv 1.2.0-52, and Rails 7.0.4.

安装了Node.js、Ruby、rbenv和Rails之后,您就可以为应用程序安装数据库了。

第一步 – 安装SQLite3

在创建Rails shark应用之前,您需要一个数据库来存储用户数据。Rails 默认配置为使用SQLite,这在开发中通常是一个不错的选择。由于应用数据不需要高级编程可扩展性,SQLite将满足应用的需求。

首先,在你的终端内更新软件包索引:

apt update

接下来,安装sqlite3和libsqlite3-dev包:

apt install sqlite3 libsqlite3-dev

这将安装SQLite及其所需的开发文件。

你可以检查版本来确认安装是否成功。

sqlite3 --version
Output
3.37.2 2022-01-06 13:25:41 872ba256cbf61d9290b571c0e6d82a20c224ca3ad82971edc46b29818d5dalt1

有了安装好的SQLite,你就可以开始开发应用程序了。

第二步-创建一个新的Rails项目。

安装数据库后,您可以使用rails new 命令创建一个新的Rails项目,并访问Rails提供的一些默认样板代码。

使用以下命令创建一个名为sharkapp的项目:

rails new sharkapp

输出显示Rails为您的新项目创建的所有不同的事物。以下输出突出显示了一些重要的文件、目录和命令。

Output
create . . . create Gemfile . . . create app . . . create app/controllers/application_controller.rb . . . create app/models/application_record.rb . . . create app/views/layouts/application.html.erb . . . create config create config/routes.rb create config/application.rb . . . create config/environments create config/environments/development.rb create config/environments/production.rb create config/environments/test.rb . . . create config/database.yml create db create db/seeds.rb . . . run bundle install . . . Bundle complete! 15 Gemfile dependencies, 69 gems now installed. Use `bundle info [gemname]` to see where a bundled gem is installed. . . .

以下是一些创建的Rails文件和文件夹的简要描述:

  • Gemfile: This file lists the gem dependencies for your application. A gem is a Ruby software package, and a Gemfile allows you to manage your project’s software needs.
  • app: The app directory is where your main application code lives. This includes the models, controllers, views, assets, helpers, and mailers that make up the application itself. Rails gives you some application-level boilerplate for the MVC model to start out in files like app/models/application_record.rb, app/controllers/application_controller.rb, and app/views/layouts/application.html.erb.
  • config: This directory contains your application’s configuration settings:config/routes.rb: Your application’s route declarations live in this file.
    config/application.rb: General settings for your application components are located in this file.
  • config/environments: This directory is where configuration settings for your environments live. Rails includes three environments by default: development, production, and test.
  • config/database.yml: Database configuration settings live in this file, which is broken into four sections: default, development, production, and test. Thanks to the Gemfile that came with the rails new command, which included the sqlite3 gem, the config/database.yml file has its adapter parameter set to sqlite3, specifying that you will use a SQLite database with this application.
  • db: This folder includes a directory for database migrations called migrate, along with the schema.rb and seeds.rb files. schema.db contains information about your database, while seeds.rb is where you can place seed data for the database.

最后,Rails运行bundle install命令来安装Gemfile中列出的依赖项。

一旦一切设置完成,导航到新的sharkapp目录。 (Yīdàn yīqiè shèzhì wánchéng, dǎoháng dào xīn de sharkapp mùlù.)

cdsharkapp

在sharkapp目录中,使用rails server命令启动Rails服务器,以确保你的应用程序正常工作。如果你在本机上工作,请输入以下代码启动服务器:

rails server

Rails默认绑定到本地主机,这意味着你可以通过在浏览器中导航至localhost:3000来访问你的应用程序。

Rails default landing page.

如果您正在使用开发服务器,请确保端口3000上允许连接。

sudo ufw allow 3000

然后使用–binding标志启动服务器,绑定到您的服务器IP地址。

rails server --binding=your_server_ip

在浏览器中导航至http://your_server_ip:3000以访问默认的Rails首页。

当你准备好了,你可以通过在终端中按下CTRL+C来停止服务器。

当您的应用程序已经创建并就位时,您可以从Rails脚手架开始构建,以创建一个独特的应用程序。

步骤三 — 构建应用程序的脚手架

要创建鲨鱼应用程序,您需要创建一个模型来管理应用程序数据,视图以使用户可以与该数据进行交互,并创建一个控制器来管理模型和视图之间的通信。要构建这些内容,可以使用Rails generate scaffold命令。该命令将生成一个模型、一个用于更改数据库架构的数据库迁移、一个控制器以及一整套用于管理应用程序的创建、读取、更新和删除(CRUD)操作的视图,还包括用于partials、helpers和tests的模板。

生成脚手架命令在底层执行了许多操作。该命令包括模型的名称以及你想要在数据库表中的字段。Rails 使用 Active Record 来管理应用数据之间的关系,构建为具有模型的对象,并存储在应用数据库中。这些模型是 Ruby 类,同时继承 ActiveRecord::Base 类。这意味着你可以像操作 Ruby 类一样操作自己的模型类。此外,还可以使用 Active Record 的方法。Active Record 确保每个类被映射到数据库中的一张表,每个类的实例被映射为该表中的一行。

运行以下命令生成一个Shark模型,控制器和相关视图:

rails generate scaffold Shark name:string facts:text

这个命令中的name:string和facts:text选项表示你在数据库表中创建的字段和它们应接受的数据类型。两者都允许你输入你想要的内容。text选项允许更多的字符。

输入此命令后,输出显示生成的所有不同文件。

Output
invoke active_record create db/migrate/20190804181822_create_sharks.rb create app/models/shark.rb . . . invoke resource_route route resources :sharks invoke scaffold_controller create app/controllers/sharks_controller.rb invoke erb create app/views/sharks create app/views/sharks/index.html.erb create app/views/sharks/edit.html.erb create app/views/sharks/show.html.erb create app/views/sharks/new.html.erb create app/views/sharks/_form.html.erb . . .

Rails在app/models/shark.rb中创建了模型,并生成了一个与之相关的数据库迁移文件:db/migrate/20190804181822_create_sharks.rb。迁移文件的时间戳与示例输出可能不同。

它还创建了一个控制器,命名为app/controllers/sharks_controller.rb,并创建了与应用的CRUD操作相关的视图,这些视图都存放在app/views/sharks下。其中包含一个部分视图 _form.html.erb,它包含了在各个视图中使用的代码。

最后,Rails在config/routes.rb中添加了一个新的资源路由,resources :sharks。这使得Rails路由器能够将传入的HTTP请求与sharks控制器及其关联的视图相匹配。

尽管Rails已经完成了大部分应用程序代码的构建工作,但值得深入研究一些文件,以更好地了解发生的情况。

要理解控制器文件,请在您的终端中输入以下命令。

cat app/controllers/sharks_controller.rb
Output
class SharksController < ApplicationController before_action :set_shark, only: %i[ show edit update destroy ] # GET /sharks or /sharks.json def index @sharks = Shark.all end # GET /sharks/1 or /sharks/1.json def show end # GET /sharks/new def new @shark = Shark.new end # GET /sharks/1/edit def edit end # POST /sharks or /sharks.json def create @shark = Shark.new(shark_params) respond_to do |format| if @shark.save format.html { redirect_to shark_url(@shark), notice: "Shark was successfully created." } format.json { render :show, status: :created, location: @shark } else format.html { render :new, status: :unprocessable_entity } format.json { render json: @shark.errors, status: :unprocessable_entity } end end end # PATCH/PUT /sharks/1 or /sharks/1.json def update respond_to do |format| if @shark.update(shark_params) format.html { redirect_to shark_url(@shark), notice: "Shark was successfully updated." } format.json { render :show, status: :ok, location: @shark } else format.html { render :edit, status: :unprocessable_entity } format.json { render json: @shark.errors, status: :unprocessable_entity } end end end # DELETE /sharks/1 or /sharks/1.json def destroy @shark.destroy respond_to do |format| format.html { redirect_to sharks_url, notice: "Shark was successfully destroyed." } format.json { head :no_content } end end private # Use callbacks to share common setup or constraints between actions. def set_shark @shark = Shark.find(params[:id]) end # Only allow a list of trusted parameters through. def shark_params params.require(:shark).permit(:name, :facts) end end

控制器负责管理信息的获取和传递给其关联模型的方式,以及将其与特定视图关联的方式。例如,鲨鱼控制器包含一系列方法,大致映射到标准的创建、读取、更新和删除操作。有更多的方法可以提高在错误情况下的效率。

举个例子,考虑一下创建方法:

~ / sharkapp / app / controllers / sharks_controller.rb 的中文释义为:~/sharkapp / app / controllers / sharks_controller.rb。
. . .
  def create
    @shark = Shark.new(shark_params)

    respond_to do |format|
      if @shark.save
        format.html { redirect_to @shark, notice: 'Shark was successfully created.' }
        format.json { render :show, status: :created, location: @shark }
      else
        format.html { render :new }
        format.json { render json: @shark.errors, status: :unprocessable_entity }
      end
    end
  end
. . . 

如果成功保存了Shark类的新实例,则redirect_to将生成一个新的请求,然后将其引导到控制器。这是一个GET请求,将由show方法处理,该方法将向用户显示他们最近添加的输入。

如果出现故障,Rails会重新渲染app/views/sharks/new.html.erb模板,而不会向路由发送另一个请求,让用户有机会重新提交数据。

除了sharks控制器外,Rails还为索引视图创建了一个模板,该模板映射到控制器中的index方法。您将使用此视图作为您的应用程序的根视图。

运行以下命令来输出文件。

cat app/views/sharks/index.html.erb
Output
<p style="color: green"><%= notice %></p> <h1>Sharks</h1> <div id="sharks"> <% @sharks.each do |shark| %> <%= render shark %> <p> <%= link_to "Show this shark", shark %> </p> <% end %> </div> <%= link_to "New shark", new_shark_path %>

索引视图循环遍历Shark类的实例,该类映射到数据库中的sharks表。使用ERB模板,视图输出与每个独立的鲨鱼实例关联的表格中的每个字段:名称和事实。

然后视图使用link_to辅助函数来创建一个超链接,提供的字符串作为链接的文本,提供的路径作为目的地。这些路径本身是通过在Rails generate scaffold命令中定义鲨鱼资源路由时可用的辅助函数变得可能的。

使用新的视图,使用部分视图。运行以下命令来返回 app/views/sharks/new.html.erb 模板:

cat app/views/sharks/new.html.erb
Output
<h1>New shark</h1> <%= render "form", shark: @shark %> <br> <div> <%= link_to "Back to sharks", sharks_path %> </div>

尽管这个模板上看起来似乎缺少一个新鲨鱼条目的输入字段,但对于渲染“表单”的引用表明该模板正在调用_form.html.erb的部分文件,该文件提取了在视图中重复出现的代码。

输出_form.html.erb文件以更全面地了解如何创建新的shark实例。

cat app/views/sharks/_form.html.erb
Output

<%= form_with(model: shark) do |form| %> <% if shark.errors.any? %> <div style="color: red"> <h2><%= pluralize(shark.errors.count, "error") %> prohibited this shark from being saved:</h2> <ul> <% shark.errors.each do |error| %> <li><%= error.full_message %></li> <% end %> </ul> </div> <% end %> <div> <%= form.label :name, style: "display: block" %> <%= form.text_field :name %> </div> <div> <%= form.label :facts, style: "display: block" %> <%= form.text_area :facts %> </div> <div> <%= form.submit %> </div> <% end %>

此模板使用form_with表单助手。表单助手旨在借助特定模型的字段和范围,方便用户通过输入创建新对象。在此示例中,form_with采用model: shark作为参数,并生成一个新的表单构建器对象,该对象的字段输入与sharks表中的字段对应。这意味着用户可以通过表单字段输入鲨鱼的名称和鲨鱼的相关信息。

提交此表单将创建一个JSON响应,其中包含用户数据,您的应用程序的其余部分可以通过params方法访问该数据。这将创建一个ActionController::Parameters对象。

既然你已经了解了Rails生成脚手架为你创建的内容,现在你可以继续设置应用程序的根视图。

第四步—创建应用程序根视图和测试功能。

理想情况下,您希望应用程序的登录页面与应用程序的根目录相匹配,这样用户就可以立即了解应用程序的目的。

例如,您可以创建一个欢迎控制器和一个相关的主页视图,为用户提供一个通用的登录页面,该页面还可以链接到应用程序的不同部分。

为了进行设置,你需要修改config/routes.rb中的路由设置,以指定应用程序的根目录。

使用nano或您喜欢的编辑器打开config/routes.rb文件进行编辑。

nano config/routes.rb
~/sharkapp/config/routes.rb的内容需要用中国汉语进行简洁的转述。
Rails.application.routes.draw do
  resources :sharks
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html

  # Defines the root path route ("/")
  # root "articles#index"
end

如果不设置其他更具体的内容,访问 http://localhost:3000 或 http://your_server_ip:3000 将显示默认的 Rails 欢迎页面。

将应用程序的根视图映射到鲨鱼控制器的索引视图,通过取消 #root “articles#index” 行前的 # 并将 article 替换为 shark,可解除注释。

~/sharkapp/config/routes.rb的中文本地化改写如下:

~/鲨鱼应用程序/配置/routes.rb

Rails.application.routes.draw do
  resources :sharks

  root 'sharks#index' 
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end

编辑完成后保存文件并退出编辑器。如果使用nano编辑器退出文件,请按下CTRL+X,Y,然后按回车键。

现在,当用户导航到您的应用程序根目录时,他们进入了鲨鱼登录页面,而不是默认的Rails登录页面。此外,他们现在有机会创建新的鲨鱼条目,查看现有的条目,并编辑或删除给定的条目。

接下来,使用以下命令运行迁移。

rails db:migrate

这个结果证实了迁移。

Output
== 20230124215633 CreateSharks: migrating ===================================== -- create_table(:sharks) -> 0.0041s == 20230124215633 CreateSharks: migrated (0.0045s) ============================

重新启动你的Rails服务器。如果你在本地工作,运行以下命令:

rails s

在开发服务器上运行:

rails s --binding=your_server_ip

如果你在本地工作,导航到localhost:3000;如果你在开发服务器上工作,导航到http://your_server_ip:3000,以访问你的新着陆页。

Application Landing Page

要创建一只新的鲨鱼,请点击“新鲨鱼”链接。该链接将带您进入鲨鱼/新建的路径。

Create New Shark

你可以添加一些信息来测试你的应用程序。在姓名字段中填写“Great White”,在事实字段中填写“Scary”。

Add Great White Shark

然后,点击“创建鲨鱼”按钮来创建鲨鱼。

这个按钮会将您导向展示路由,而这得益于 before_action 过滤器的设置,在 set_shark 方法中,它会获取您创建的鲨鱼的 id。

~/sharkapp/app/controllers/sharks_controller.rb的内容再用中文进行释义如下:
class SharksController < ApplicationController
  before_action :set_shark, only: %i[ show edit update destroy ]

  . . . 
  # GET /sharks/1 or /sharks/1.json
  def show
  end

  . . . 

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_shark
      @shark = Shark.find(params[:id])
    end
  . . .
Show Shark

你可以通过点击“修改此鲨鱼”来测试编辑功能。这将带你进入该鲨鱼的编辑界面。

Edit Shark

更新有关大白鲨的事实,将”吓人”改为”巨大”,然后点击更新鲨鱼。这将带您回到节目路线。

Updated Shark

最后,点击返回到鲨鱼页面会带您进入更新后的索引视图。

New Index View

现在您已经测试了应用程序的基本功能,您可以添加一些验证和安全检查,以使所有东西更加安全。

第五步— 添加验证

你的鲨鱼应用程序可以接受用户输入,但想象一个情况,用户试图创建一个没有添加任何信息的鲨鱼,或者创建一个已经存在于数据库中的鲨鱼条目。你可以通过为模型添加验证机制,在数据输入进入数据库之前对数据进行检查。由于应用程序的逻辑位于其模型中,因此在此处验证数据输入是合适的。

请注意,本教程不包括编写验证测试的内容,但您可以通过查阅Rails文档来获取更多有关测试的信息。

如果您还没有停止服务器,请立即在终端中按下CTRL+C来停止服务器。

打开你的shark.rb模型文件。

nano app/models/shark.rb

目前,文件告诉我们,Shark类从ApplicationRecord继承,而ApplicationRecord又从ActiveRecord::Base继承。

~/sharkapp/app/models/shark.rb的内容进行中文本地化翻译:
~/sharkapp/app/models/shark.rb文件
class Shark < ApplicationRecord
end

在名称字段中添加一些验证,以确认该字段已填写且输入是唯一的,以防止重复输入。

~/sharkapp/app/models/shark.rb的以下内容进行本地化的中文释义,只需要一个选项:
class Shark < ApplicationRecord
  validates :name, presence: true, uniqueness: true
end

接下来,为事实字段添加验证,以确保它也被填写。

~/sharkapp/app/models/shark.rb的内容

(Translation: The content of ~/sharkapp/app/models/shark.rb)

class Shark < ApplicationRecord
  validates :name, presence: true, uniqueness: true
  validates :facts, presence: true
end

以下是对其进行汉语本地化的一种转述:验证代码的“验证:facts,presence:true”行与事实的独特性无关,而是与唯一的鲨鱼条目相关联进行验证。

完成后请保存并关闭文件。

再次使用rails s或rails s –binding=your_server_ip启动您的服务器,然后在http://localhost:3000或http://your_server_ip:3000导航到您的应用程序的根目录。

点击“新鲨鱼”链接。在表格中,将“Great White”添加到名称字段,“Big Teeth”添加到事实字段,然后点击创建鲨鱼。在这种情况下会出现一个警告信息。

Unique Validation Warning

为了检查其他验证,请点击“回到鲨鱼”返回主页,然后再次点击“新的鲨鱼”。在新的表格中,将“名字”字段输入为“虎鲨”,将“事实”字段留空。当您点击“创建鲨鱼”时,会输出以下警告:

Fact Presence Warning

有了这些变化,您的应用程序进行了一些验证,以确保保存到数据库中的数据的一致性。现在您可以关注于应用程序的用户,并定义谁可以修改应用程序数据。

步骤6 — 添加身份验证

有一些验证机制,你可以确保保存到数据库的数据是可靠的。但是对于用户呢?如果你不希望任何人都能向数据库中添加数据,那么你应该添加一些身份验证措施,以确保只有被允许的用户可以添加鲨鱼信息。为了实现这一点,可以使用 http_basic_authenticate_with 方法,该方法允许创建用户名和密码的组合来对用户进行身份验证。

在Rails中,有许多方法可以用于用户认证,包括使用bcrypt或devise宝石。但是,现在,向您的应用程序控制器添加一个方法,该方法将适用于应用程序中的各个操作。如果您将来添加更多控制器到应用程序中,这将非常有用。

使用CTRL+C停止你的服务器。

打开定义你的ApplicationController的文件。

nano app/controllers/application_controller.rb

在这里是ApplicationController类的定义,你的应用程序中的其他控制器都继承自它。

请在中国的本地语言中进行释义:~/sharkapp/app/controllers/application_controller.rb
「~/sharkapp/app/controllers/application_controller.rb」是应用程序控制器的代码文件路径。
class ApplicationController < ActionController::Base
end

为了验证用户,使用带有http_basic_authenticate_with方法的硬编码用户名和密码。将以下代码添加到文件中。

请将以下内容在中文中进行改写(只需一种方式):
~/sharkapp/app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  http_basic_authenticate_with name: 'sammy', password: 'shark', except: [:index, :show]
end

除了在这里提供用户名和密码之外,您还通过指定不需要认证的路由来限制了认证:索引和展示。另一种实现方式是仅写:[:create, :update, :destroy]。这样,所有用户都将能够访问所有的鲨鱼,并阅读有关特定鲨鱼的信息。然而,当涉及修改网站内容时,用户将需要证明他们有访问权限。

在一个更健壮的设置中,你不会想以这种方式硬编码数值,但这个示例展示了如何为应用的路由包括身份验证。Rails默认将会话数据存储在cookies中:一旦你在特定操作上进行身份验证,你在同一会话中将不需要再次进行身份验证。

在编辑完之后,保存并关闭app/controllers/application_controller.rb文件。现在,您可以测试身份验证功能了。

使用rails s或rails s –binding=your_server_ip启动服务器,并在http://localhost:3000或http://your_server_ip:3000上访问您的应用程序。

在登陆页面上,点击“新建鲨鱼”按钮。这将触发以下认证窗口。

User Authentication

如果您输入的用户名是sammy,密码是shark,并且这是您添加到app/controllers/application_controller.rb的组合,您将能够安全地创建一个新的shark。

你现在拥有一个完美运行的鲨鱼应用,包括数据验证和基本的认证方案。

结论

在本教程中创建的Rails应用程序是一个可以用于进一步开发的起点。如果你对探索Rails生态系统感兴趣,项目文档是一个很好的开始地点。

你还可以通过阅读《如何为Ruby on Rails应用程序创建嵌套资源》来了解更多关于将嵌套资源添加到你的项目中的知识,这篇文章将向你展示如何构建应用程序的模型和路由。

此外,你可能想要尝试使用React等框架来为你的项目设置更强大的前端。《如何使用React前端设置Ruby on Rails项目》提供了关于如何实现这个目标的指导。

如果您想探索不同的数据库选项,您也可以查阅《如何在Ubuntu 20.04上使用PostgreSQL与Ruby on Rails应用程序》,其中介绍了如何使用PostgreSQL而不是SQLite。您还可以查阅我们的PostgreSQL教程库,以了解更多关于使用这个数据库的内容。

发表回复 0

Your email address will not be published. Required fields are marked *