如何构建Ruby on Rails应用程序

Rails是一个用Ruby编写的Web应用程序框架。它采用了一种固执的应用程序开发方法,假设在有共同目标的情况下,集合约定最好地为开发人员服务。 在本教程中,您将构建一个Rails应用程序,该应用程序将使用户能够发布有关鲨鱼的信息并对其他用户的帖子发表评论,从而创建有关鲨鱼及其行为的更大对话。

介绍

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

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

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

先决条件

要学习本教程,您需要:

第1步 - 安装SQLite3

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

首先,更新包索引:

sudo apt update

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

sudo apt install sqlite3 libsqlite3-dev

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

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

sqlite3 --version
3.22.0 2018-01-22 18:45:57 0c55d179733b46d8d0ba4d88e01a25e10677046ee3da1d5b1581e86726f2alt1

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

第2步 - 创建新的Rails项目

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

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

rails new sharkapp

您将看到大量输出,告诉您Rails为您的新项目创建的内容。 下面的输出突出显示了一些重要的文件,目录和命令:

     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参数设置为sqlite3 ,指定我们将在此应用程序中使用SQLite数据库。
  • db :此文件夹包含一个名为migrate数据库迁移目录,以及schema.rbseeds.rb文件。 schema.db包含有关数据库的信息,而seeds.rb是您可以为数据库放置种子数据的位置。

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

设置完所有内容后,导航到sharkapp目录:

cd sharkapp

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

rails server 

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

Rails登陆页面

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

sudo ufw allow 3000

然后使用--binding标志启动服务器,以绑定到您的服务器IP:

rails server --binding=your_server_ip

在浏览器中导航到http:// your_server_ip :3000 ,您将在其中看到Rails欢迎消息。

环顾四周后,您可以使用CTRL+C停止服务器。

创建并准备好应用程序后,您就可以从Rails样板开始构建,以创建一个独特的应用程序。

第3步 - 脚手架应用程序

要创建我们的鲨鱼信息应用程序,我们需要创建一个模型来管理我们的应用程序数据,视图以实现用户与该数据的交互,以及一个控制器来管理模型和视图之间的通信。 要构建这些东西,我们将使用rails generate scaffold命令,它将为我们提供模型, 数据库迁移以更改数据库模式,控制器,管理创建,读取,更新和删除的全套视图(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为您生成的所有内容。 下面的输出突出显示了我们设置的一些更重要的事情:

      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 ,以及与app/views/sharks下收集的应用程序的CRUD操作相关的app/views/sharks 这些视图中有一个部分的_form.html.erb ,其中包含跨视图使用的代码。

最后,Rails添加了一条新的资源丰富的路由, resources :sharksconfig/routes.rb 这使Rails路由器能够将传入的HTTP请求与sharks控制器及其相关视图进行匹配。

虽然Rails已经完成了为我们构建应用程序代码的大部分工作,但值得一看有些文件来了解正在发生的事情。

首先,让我们使用以下命令查看控制器文件:

cat app/controllers/sharks_controller.rb
class 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 /应用/控制器/ 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
<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模板 ,视图输出与单个shark实例关联的表中的每个字段: namefacts

然后,视图使用link_to帮助程序创建超链接,提供的字符串作为链接的文本,提供的路径作为目标。 当我们使用rails generate scaffold命令定义sharks资源路径时,通过我们可用的帮助程序可以实现路径本身。

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

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

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

<%= link_to 'Back', sharks_path %>

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

查看该文件将让我们充分了解如何创建新的shark实例:

cat app/views/sharks/_form.html.erb
<%= 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_withmodel: shark作为参数,并且它创建的新表单构建器对象具有与sharks表中的字段对应的字段输入。 因此,用户具有表单字段以输入鲨鱼name和鲨鱼facts

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

既然您已经了解了rails generate scaffold ,您可以继续设置应用程序的根视图。

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

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

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

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

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

nano config/routes.rb

该文件将如下所示:

〜/ sharkapp /配置/ 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欢迎页面。

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

〜/ sharkapp /配置/ 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路线:

创造新的鲨鱼

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

添加大白鲨

单击“ 创建”按钮以创建鲨鱼。

这将引导您进入show route,由于before_action过滤器,使用set_shark方法设置,该方法获取我们刚刚创建的鲨鱼的id

〜/ sharkapp /应用/控制器/ 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路线:

编辑鲨鱼

将有关Great White的facts更改为“Large”而不是“Scary”,然后单击Update Shark 这将带您回到show路线:

更新了鲨鱼

最后,单击Back将转到更新的index视图:

新索引视图

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

第5步 - 添加验证

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

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

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

打开shark.rb模型文件:

nano app/models/shark.rb

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

〜/ sharkapp /应用/模型/ shark.rb
class Shark < ApplicationRecord
end

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

〜/ sharkapp /应用/模型/ shark.rb
class Shark < ApplicationRecord
  validates :name, presence: true, uniqueness: true
end

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

〜/ sharkapp /应用/模型/ 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 在表单中,将“Great White”添加到Name字段,将“Big Teeth”添加到Facts字段,然后单击Create Shark 您应该看到以下警告:

唯一验证警告

现在,让我们看看我们是否可以检查其他验证。 单击“ 返回”返回主页,然后再次返回“ 新鲨鱼” 在新表单中,在“ 名称”字段中输入“Tiger Shark”,并将Facts留空。 单击Create Shark将触发以下警告:

事实存在警告

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

第6步 - 添加身份验证

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

有许多方法可以使用Rails对用户进行身份验证,包括使用bcryptdevise gems。 但是,现在,我们将向应用程序控制器添加一个方法,该方法将应用于整个应用程序中的操作。 如果我们将来向应用程序添加更多控制器,这将非常有用。

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

打开定义ApplicationController的文件:

nano app/controllers/application_controller.rb

在里面,您将看到ApplicationController类的定义, ApplicationController中的其他控制器继承该定义:

〜/ sharkapp /应用/控制器/ application_controller.rb
class ApplicationController < ActionController::Base
end

要对用户进行身份验证,我们将使用带有http_basic_authenticate_with方法的硬编码用户名和密码。 将以下代码添加到文件中:

〜/ sharkapp /应用/控制器/ application_controller.rb
class ApplicationController < ActionController::Base
  http_basic_authenticate_with name: 'sammy', password: 'shark', except: [:index, :show]
end

除了在这里提供用户名和密码之外,我们还通过指定不需要的路由来限制身份验证: indexshow 实现这一目标的另一种方法是only: [:create, :update, :destroy]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生态系统, 项目文档是一个很好的起点。

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

如果您想探索不同的数据库选项,您还可以在Ubuntu 18.04上查看如何在Ruby on Rails应用程序中使用PostgreSQL ,该应用程序将介绍如何使用PostgreSQL而不是SQLite。 您还可以查阅我们的PostgreSQL教程库,以了解有关使用此数据库的更多信息。