如何构建RubyonRails应用程序

来自菜鸟教程
跳转至:导航、​搜索

介绍

Rails 是一个用 Ruby 编写的 Web 应用程序框架。 它对应用程序开发采取了一种固执己见的方法,假设集合约定最好地为有共同目标的开发人员服务。 因此,Rails 提供了处理路由、有状态数据、资产管理等的约定,以提供大多数 Web 应用程序所需的基线功能。

Rails 遵循 model-view-controller (MCV) 架构模式,它将位于模型中的应用程序逻辑与应用程序信息的路由和呈现分开。 这种组织结构——以及允许开发人员将代码提取到 helperspartials 的其他约定——确保应用程序代码不会 不必要地重复

在本教程中,您将构建一个 Rails 应用程序,使用户能够发布有关鲨鱼及其行为的信息。 这将是未来应用程序开发的良好起点。

先决条件

要遵循本教程,您将需要:

  • 运行 Ubuntu 18.04 的本地机器或开发服务器。 您的开发机器应该有一个具有管理权限的非 root 用户和一个配置了 ufw 的防火墙。 有关如何设置的说明,请参阅我们的 Initial Server Setup with Ubuntu 18.04 教程。
  • Node.jsnpm 安装在本地机器或开发服务器上。 本教程使用 Node.js 版本 10.16.3 和 npm 版本 6.9.0。 有关在 Ubuntu 18.04 上安装 Node.js 和 npm 的指导,请按照 如何在 Ubuntu 18.04 上安装 Node.js 的“使用 PPA 安装”部分中的说明进行操作。
  • Ruby、rbenv 和 Rails 安装在本地计算机或开发服务器上,遵循 如何在 Ubuntu 18.04 上使用 rbenv 安装 Ruby on Rails 中的步骤 1-4。 本教程使用 Ruby 2.5.1、rbenv 1.1.2 和 Rails 5.2.0

第 1 步 — 安装 SQLite3

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

首先,更新你的包索引:

sudo apt update

接下来,安装 sqlite3libsqlite3-dev 软件包:

sudo apt install sqlite3 libsqlite3-dev

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

检查您的版本以确认安装成功:

sqlite3 --version
Output3.22.0 2018-01-22 18:45:57 0c55d179733b46d8d0ba4d88e01a25e10677046ee3da1d5b1581e86726f2alt1

安装 SQLite 后,您就可以开始开发应用程序了。

第 2 步——创建一个新的 Rails 项目

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

使用以下命令创建一个名为 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! 18 Gemfile dependencies, 78 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
      . . . 
* bin/rake: Spring inserted
* bin/rails: Spring inserted

此处突出显示的输出告诉您 Rails 创建了以下内容:

  • Gemfile:此文件列出了您的应用程序的 gem 依赖项。 gem 是一个 Ruby 软件包,Gemfile 允许您管理项目的软件需求。
  • appapp 目录是您的主要应用程序代码所在的位置。 这包括构成应用程序本身的模型、控制器、视图、资产、帮助程序和邮件程序。 Rails 为您提供了一些 MCV 模型的应用程序级样板,可以从 app/models/application_record.rbapp/controllers/application_controller.rbapp/views/layouts/application.html.erb 等文件开始。
  • config :此目录包含您的应用程序的配置设置: config/routes.rb:您的应用程序的路由声明位于此文件中。 config/application.rb:应用程序组件的常规设置位于此文件中。
  • config/environments:此目录是您的环境的配置设置所在的目录。 Rails 默认包含三个环境:developmentproductiontest
  • config/database.yml:数据库配置设置位于此文件中,分为四个部分:defaultdevelopmentproductiontest . 感谢 rails new 命令附带的 Gemfile,其中包括 sqlite3 gem,我们的 config/database.yml 文件将其 adapter 参数设置为 [ X152X],指定我们将在此应用程序中使用 SQLite 数据库。
  • db:此文件夹包括一个名为 migrate 的数据库 migrations 目录,以及 schema.rbseeds.rb 文件。 schema.db 包含有关您的数据库的信息,而 seeds.rb 是您可以放置数据库种子数据的位置。

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

一切设置好后,导航到 sharkapp 目录:

cd sharkapp

您现在可以使用 rails 服务器命令 启动 Rails 服务器以确保您的应用程序正常工作。 如果您在本地计算机上工作,请键入:

rails server 

Rails 默认绑定到 localhost,因此您现在可以通过将浏览器导航到 locahost:3000 来访问您的应用程序,您将在其中看到以下图像:

如果您在开发服务器上工作,请首先确保端口 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 命令,它会给我们一个模型,一个 数据库迁移 来改变数据库模式,一个控制器,一套完整的视图来管理 [X189X ]为应用程序创建、读取、更新和删除 (CRUD) 操作,以及用于部分、帮助程序和测试的模板。

因为 generate scaffold 命令为我们做了很多工作,我们将仔细查看它创建的资源,以了解 Rails 在后台所做的工作。

我们的 generate scaffold 命令将包括我们模型的名称和我们想要在我们的数据库表中的字段。 Rails 使用 Active Record 来管理应用程序数据(构建为具有模型的对象)与应用程序数据库之间的关系。 我们的每个模型都是 Ruby 类,同时也继承自 ActiveRecord::Base 类。 这意味着我们可以像使用 Ruby 类一样使用模型类,同时还可以从 Active Record 中提取方法。 Active Record 将确保每个类都映射到我们数据库中的一个表,并且该类的每个实例都映射到该表中的一行。

键入以下命令以生成 Shark 模型、控制器和关联视图:

rails generate scaffold Shark name:string facts:text

通过 name:stringfacts:text,我们向 Rails 提供了有关我们希望在数据库表中的字段以及它们应该接受的数据类型的信息。 虽然 text 将允许更多字符用于鲨鱼事实,但两者都将给我们输入我们想要的内容的空间。

当您键入此命令时,您将再次看到一长串输出,其中解释了 Rails 为您生成的所有内容。 下面的输出突出了我们设置的一些更重要的事情:

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
Outputclass SharksController < ApplicationController
  before_action :set_shark, only: [:show, :edit, :update, :destroy]

  # GET /sharks
  # GET /sharks.json
  def index
    @sharks = Shark.all
  end

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

  # GET /sharks/new
  def new
    @shark = Shark.new
  end

  # GET /sharks/1/edit
  def edit
  end

  # POST /sharks
  # POST /sharks.json
  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

  # PATCH/PUT /sharks/1
  # PATCH/PUT /sharks/1.json
  def update
    respond_to do |format|
      if @shark.update(shark_params)
        format.html { redirect_to @shark, notice: 'Shark was successfully updated.' }
        format.json { render :show, status: :ok, location: @shark }
      else
        format.html { render :edit }
        format.json { render json: @shark.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /sharks/1
  # DELETE /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

    # Never trust parameters from the scary internet, only allow the white list through.
    def shark_params
      params.require(:shark).permit(:name, :facts)
    end
end

控制器负责管理如何获取信息并将其传递给其关联模型,以及如何与特定视图关联。 如您所见,我们的 sharks 控制器包含一系列大致映射到标准 CRUD 操作的方法。 但是,除了 CRUD 函数之外,还有更多方法可以在出现错误的情况下提高效率。

例如,考虑 create 方法:

~/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 模板,而不是向路由器发出另一个请求,从而为用户提供另一个提交数据的机会。

除了鲨鱼控制器之外,Rails 还为我们提供了 index 视图的模板,它映射到我们控制器中的 index 方法。 我们将使用它作为我们应用程序的根视图,因此值得一看。

键入以下内容以输出文件:

cat app/views/sharks/index.html.erb
Output<p id="notice"><%= notice %></p>

<h1>Sharks</h1>

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Facts</th>
      <th colspan="3"></th>
    </tr>
  </thead>

  <tbody>
    <% @sharks.each do |shark| %>
      <tr>
        <td><%= shark.name %></td>
        <td><%= shark.facts %></td>
        <td><%= link_to 'Show', shark %></td>
        <td><%= link_to 'Edit', edit_shark_path(shark) %></td>
        <td><%= link_to 'Destroy', shark, method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <% end %>
  </tbody>
</table>

<br>

<%= link_to 'New Shark', new_shark_path %>

index 视图遍历我们的 Shark 类的实例,这些实例已映射到我们数据库中的 sharks 表。 使用 ERB 模板,视图输出与单个鲨鱼实例关联的表中的每个字段:namefacts

然后视图使用 link_to 帮助器创建一个超链接,提供的字符串作为链接的文本,提供的路径作为目标。 当我们使用 rails generate scaffold 命令定义 sharks 资源路由时,我们可以使用 helpers 使路径本身成为可能。

除了查看我们的 index 视图之外,我们还可以查看 new 视图以了解 Rails 如何在视图中使用局部视图。 键入以下内容以输出 app/views/sharks/new.html.erb 模板:

cat app/views/sharks/new.html.erb
Output<h1>New Shark</h1>

<%= render 'form', shark: @shark %>

<%= link_to 'Back', sharks_path %>

虽然这个模板可能看起来缺少新鲨鱼条目的输入字段,但对 render 'form' 的引用告诉我们模板正在拉入 _form.html.erb 部分,它提取跨视图重复的代码.

查看该文件将使我们全面了解如何创建新的鲨鱼实例:

cat app/views/sharks/_form.html.erb
Output<%= form_with(model: shark, local: true) do |form| %>
  <% if shark.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(shark.errors.count, "error") %> prohibited this shark from being saved:</h2>

      <ul>
      <% shark.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= form.label :name %>
    <%= form.text_field :name %>
  </div>

  <div class="field">
    <%= form.label :facts %>
    <%= form.text_area :facts %>
  </div>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

该模板使用 form_with form helper。 表单助手旨在促进使用特定模型的字段和范围从用户输入创建新对象。 在这里,form_withmodel: shark 作为参数,它创建的新表单构建器对象具有与 sharks 表中的字段对应的字段输入。 因此,用户有表单域来输入鲨鱼 name 和鲨鱼 facts

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

现在您知道 rails generate scaffold 为您生成了什么,您可以继续为您的应用程序设置根视图。

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

理想情况下,您希望应用程序的登录页面映射到应用程序的根目录,以便用户可以立即了解应用程序的用途。

您可以通过多种方式处理此问题:例如,您可以创建一个 Welcome 控制器和一个关联的 index 视图,这将为用户提供一个通用的登录页面,该页面也可以链接到应用程序的不同部分。 然而,在我们的例子中,让用户登陆我们的 index 鲨鱼视图就足以介绍应用程序的用途了。

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

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

nano config/routes.rb

该文件将如下所示:

~/sharkapp/config/routes.rb

Rails.application.routes.draw do
  resources :sharks
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end

如果不设置更具体的内容,http://localhost:3000http://your_server_ip:3000 的默认视图将是默认的 Rails 欢迎页面。

为了将应用程序的根视图映射到鲨鱼控制器的 index 视图,您需要在文件中添加以下行:

~/sharkapp/config/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+XY,然后按 ENTER

您现在可以使用以下命令运行迁移:

rails db:migrate

您将看到确认迁移的输出。

再次启动 Rails 服务器。 如果您在本地工作,请键入:

rails s

在开发服务器上,键入:

rails s --binding=your_server_ip

如果您在本地工作,请导航到 localhost:3000,如果您在开发服务器上工作,请导航到 http://your_server_ip:3000

您的应用程序登录页面将如下所示:

要创建新鲨鱼,请点击页面底部的 New Shark 链接,这将带您到 sharks/new 路线:

让我们添加一些演示信息来测试我们的应用程序。 在 Name 字段中输入“Great White”,在 Facts 字段中输入“Scary”:

点击Create按钮创建鲨鱼。

这会将您定向到 show 路由,由于 before_action 过滤器,该路由是使用 set_shark 方法设置的,该方法获取 id 的我们刚刚创建的鲨鱼:

~/sharkapp/app/controllers/sharks_controller.rb

class SharksController < ApplicationController
  before_action :set_shark, only: [:show, :edit, :update, :destroy]

  . . . 

  def show
  end

  . . . 

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

您现在可以通过单击鲨鱼条目上的 Edit 来测试编辑功能。 这将带你到该鲨鱼的 edit 路线:

将Great White的facts改为“Large”而不是“Scary”,然后点击Update Shark。 这将带你回到 show 路线:

最后,单击 Back 将带您进入更新后的 index 视图:

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

第 5 步 - 添加验证

您的鲨鱼应用程序可以接受来自用户的输入,但想象一下这样一种情况:用户尝试创建鲨鱼而不向其添加事实,或者为已经在数据库中的鲨鱼创建条目。 您可以通过向模型添加验证来创建在数据输入数据库之前检查数据的机制。 由于您的应用程序的逻辑位于其模型中,因此在此处验证数据输入比在应用程序的其他地方验证数据更有意义。

请注意,我们不会在本教程中介绍如何编写验证测试,但您可以通过查阅 和 Rails 文档 了解更多关于测试的信息。

如果您还没有停止服务器,请继续输入 CTRL+C

打开您的 shark.rb 模型文件:

nano app/models/shark.rb

目前,该文件告诉我们 Shark 类继承自 ApplicationRecord,而后者又继承自 ActiveRecord::Base

~/sharkapp/app/models/shark.rb

class Shark < ApplicationRecord
end

让我们首先向我们的 name 字段添加一些验证,以确认该字段已填写并且条目是唯一的,以防止重复条目:

~/sharkapp/app/models/shark.rb

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

接下来,为 facts 字段添加验证,以确保它也被填写:

~/sharkapp/app/models/shark.rb

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

我们在这里不太关心事实的唯一性,只要它们与独特的鲨鱼条目相关联。

完成后保存并关闭文件。

使用 rails srails s --binding=your_server_ip 再次启动服务器,具体取决于您是在本地工作还是使用开发服务器。

http://localhost:3000http://your_server_ip:3000 导航到应用程序的根目录。

点击 New Shark。 在表单中,在 Name 字段中添加“Great White”,在 Facts 字段中添加“Big Teeth”,然后单击 Create Shark。 您应该看到以下警告:

现在,让我们看看我们是否可以检查我们的其他验证。 点击【X6X】返回【X14X】返回首页,再点击【X56X】New Shark【X69X】。 在新表单中,在 Name 字段中输入“Tiger Shark”,并将 Facts 留空。 点击Create Shark会触发如下警告:

通过这些更改,您的应用程序进行了一些验证,以确保保存到数据库的数据的一致性。 现在您可以将注意力转向应用程序的用户并定义可以修改应用程序数据的人员。

第 6 步 — 添加身份验证

有了验证,我们对保存到数据库的数据有了一些保证。 但是用户呢? 如果我们不希望任何和所有用户都添加到数据库中,那么我们应该添加一些身份验证措施以确保只有允许的用户才能添加鲨鱼。 为此,我们将使用 http_basic_authenticate_with 方法 ,它允许我们创建用户名和密码组合来验证用户。

有多种方法可以使用 Rails 验证用户身份,包括使用 bcryptdevise gems。 然而,现在,我们将向我们的应用程序控制器添加一个方法,该方法将应用于我们的应用程序中的操作。 如果我们将来向应用程序添加更多控制器,这将很有用。

使用 CTRL+C 再次停止服务器。

打开定义 ApplicationController 的文件:

nano app/controllers/application_controller.rb

在内部,您将看到 ApplicationController 类的定义,应用程序中的其他控制器继承自该类:

~/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

除了在此处提供用户名和密码外,我们还通过指定需要 而不是 的路由来限制身份验证:indexshow。 另一种实现这一点的方法是编写 only: [:create, :update, :destroy]。 这样,所有用户将能够查看所有鲨鱼并阅读有关特定鲨鱼的事实。 但是,在修改网站内容时,用户需要证明他们有权访问。

在更健壮的设置中,您不希望以这种方式对值进行硬编码,但出于演示的目的,这将允许您了解如何为应用程序的路由包含身份验证。 它还可以让您了解 Rails 默认情况下如何在 cookie 中存储会话数据:一旦您对指定的操作进行身份验证,您将无需在同一会话中再次进行身份验证。

编辑完成后保存并关闭app/controllers/application_controller.rb。 您现在可以实际测试身份验证。

使用 rails srails s --binding=your_server_ip 启动服务器并在 http://localhost:3000http://your_server_ip:3000 导航到您的应用程序。

在登录页面上,单击 New Shark 按钮。 这将触发以下身份验证窗口:

如果您输入您添加到 app/controllers/application_controller.rb 的用户名和密码组合,您将能够安全地创建新鲨鱼。

您现在有一个工作的鲨鱼应用程序,完成了数据验证和一个基本的身份验证方案。

结论

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

您还可以通过阅读 如何为 Ruby on Rails 应用程序创建嵌套资源 来了解有关向项目添加嵌套资源的更多信息,它将向您展示如何构建应用程序的模型和路由。

此外,您可能想探索如何使用 React 等框架为您的项目设置更强大的前端。 如何使用 React 前端设置 Ruby on Rails 项目 提供了有关如何执行此操作的指南。

如果您想探索不同的数据库选项,还可以查看 How To Use PostgreSQL with Your Ruby on Rails Application on Ubuntu 18.04,其中介绍了如何使用 PostgreSQL SQLite 的。 您还可以查阅我们的 PostgreSQL 教程 库,了解有关使用此数据库的更多信息。