如何用Rails和CockroachDB建立一个完整的网络应用程序

8,550 阅读5分钟

为了展示在实际项目中使用CockroachDB是多么容易,我们将建立并部署一个具有基本CRUD功能的生产就绪的应用程序。我们将一起建立一个Ruby on Rails应用程序,模拟一个游戏排行榜,使用Active Record与CockroachDB无服务器数据库进行对话。Cockroach实验室维护着ActiveRecord Adapter Gem,它是PostgreSQL适配器的直接扩展。这使得从默认选项切换到CockroachDB变得非常简单明了。

我们将使用Ruby 3.0来构建一个运行Rails 6.1.4版本的Rails应用。在教程的最后,我们将在Heroku上把应用部署到互联网上,Heroku在幕后运行于AWS。

设置你的环境

我们通过安装Homebrew开始这个过程。我们将使用Homebrew来安装rbenv,我们可以用它来轻松地在Ruby版本之间切换。

如果你的机器上还没有安装Ruby,根据你的系统和/或偏好,有许多不同的方法来安装该语言。因为Ruby最初是围绕基于Unix的系统开发的,在Windows机器上开发需要一些额外的设置。许多使用macOS的开发者喜欢使用rbenv来安装Ruby版本并在它们之间切换。如果你还没有一个Ruby版本管理器,并且想使用rbenv,你可以在终端运行以下命令来安装rbenv。

brew install rbenv

接下来,你必须使用你的Ruby版本管理器来安装语言本身。如果你使用rbenv,你可以用下面的命令安装Ruby 3.0.0。请记住,rbenv安装的是openssl、readline、automake和libyaml等依赖项。Ruby将从源代码编译,所以这可能需要一些时间。拿一杯你最喜欢的饮料。出去走走。冥想。与你的上帝讲和。

rbenv install 3.0.3

安装完rbenv后,按照说明设置你的路径。这可能会根据你的机器而改变,但它会看起来像这样的命令。

export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"

然后,将你的当前目录改为Ruby 3.0.3。

rbenv local 3.0.3

最后,通过运行以下命令全局安装Rails。

gem install rails -v 6.1.4.4

现在你已经拥有了使用Ruby on Rails创建令人难以置信的体验所需的大部分依赖和工具。

创建应用程序

一旦你安装了所有必要的软件包,使用rails new命令来生成一个新的Rails项目。

rails \_6.1.4.4\_ new game-leaderboard

有些系统,如Windows,可能需要在运行此命令前安装额外的依赖项,所以如果你在Windows上工作,请务必遵循链接的说明。另外,有些系统可能要求在运行此命令时不要在版本号周围加上下划线。

接下来,进入你的应用程序的新创建的目录。

cd game-leaderboard

在你创建一个新的应用程序后,运行你的服务器是一个很好的方法,以确保事情从一开始就工作得很好。用以下命令在本地运行该应用程序。

rails server

在你的浏览器中导航到localhost:3000 。如果一切工作正常,你会看到一个与此类似的屏幕。

Yay! You’re on Rails

在你运行其他东西之前,在你的终端输入CTRL+C ,终止本地服务器。

现在,让我们添加CockroachDB Active Record Adapter。在应用程序的Gemfile中,通过添加以下一行来添加具有正确版本的gem。

gem 'activerecord-cockroachdb-adapter', '~> 6.1.4'

在你捆绑之前,你必须先安装postgres。

brew install postgresql

接下来,运行以下命令。

bundle install

现在我们有了一个具有正确依赖性的应用程序,我们将创建一个CockroachDB无服务器账户。然后,我们将扩展该应用的功能。

创建一个CockroachDB无服务器账户

Cockroach Serverless创建一个账户是简单而免费的。你可以通过用电子邮件注册或连接到GitHub账户来创建一个账户。

Creating a CockroachDB Serverless Account

一旦你注册了,向导会引导你创建一个集群。这给你提供了选择诸如云提供商的选项。

确保你注意到所提供的密码。我们稍后再来讨论其他事情让你的浏览器的这个标签打开,这样你就可以在我们连接应用程序时参考它。

构建应用程序

开发人员并不总是有机会从头开始一个项目。所以在本教程中,我们将用默认的数据库设置来构建应用程序,然后切换到CockroachDB。

我们要建立一个游戏排行榜,所以我们需要有一个分数列表,以及每个分数的拥有者,最好是按分数的降序排列。对于我们的应用程序来说,正在进行的游戏并不重要。

因为Rails非常强调模型-视图-控制器的架构,所以我们首先要从模型的角度来阐述这个问题。我们想要一个可以包含用户名和分数的模型。传统上,一个球员有一个分数,所以我们将创建一个具有用户名和分数属性的用户模型。

我们可以手动创建必要的文件和代码,但Rails有一些生成工具,可以让我们不费吹灰之力就接近我们需要的东西。

在项目的根目录下,从你的命令行运行以下命令。

rails generate scaffold user

这将创建以下对象。

  • 迁移文件,以创建一个用户表。
  • 一个用户对象的模型文件。
  • 用户资源的路由。
  • 一个用于用户对象的控制器。
  • 测试文件,我们在本教程中不会用到。

因为我们只创建了迁移文件,我们仍然需要运行它。

用下面的命令来运行任何待定的迁移文件。

rails db:migrate

这将在你的本地SQLite 3数据库中创建表。它还会改变项目中的模式,以反映新表的情况。

现在你的db/schema.rb 文件应该与此相似。

ActiveRecord::Schema.define(version: 2022_01_09_212905) do

  create_table "users", force: :cascade do |t|
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end

end

在定义中你会有一个不同的版本,可能还有一些注释在上面,但其他的东西应该都是一样的。

你的用户模型将有一个string 类型的用户名属性和一个整数类型的score 属性。我们将使用一个迁移来创建这些表。

在你的终端,运行下面的命令。

rails generate migration AddUsernameToUser

与我们刚才做的第一个迁移不同,Rails并没有自动生成代码。相反,它创建了一个文件。你会在db/migrate 文件夹中找到你的迁移,文件名类似于add_username_to_user

在进行任何修改之前,迁移文件只包含一个空的修改方法。

class AddUsernameToUser < ActiveRecord::Migration\[6.1]
  def change
  end
end

我们将在改变方法中添加一行,在我们的users 表中添加一个列,这个列的类型是string ,并且不允许有null 的值。你的迁移看起来应该是这样的。

class AddUsernameToUser < ActiveRecord::Migration\[6.1]
  def change
    add_column :users, :username, :string, null: false
  end
end

接下来,用下面的命令再运行一次迁移。

rails db:migrate

我们将使用类似的过程来创建分数列,但是它的类型是integer ,默认值是0

通过运行下面的命令来创建迁移。

rails generate migration AddScoreToUser

然后,在新创建的迁移文件中,在change方法里面添加必要的add_column 调用。

add_column :users, :score, :integer, default: 0

最后,运行下面的命令来完成。

rails db:migrate

现在我们需要向已经生成的用户表单添加字段。这样,应用程序的用户就可以用正确的值创建新的对象并更新现有的对象。

app/views/users/_form.html.erb ,添加用户名和分数值的字段。你的整个文件应该看起来像这样。

<%= form_with(model: user) do |form| %>
  <% if user.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(user.errors.count, "error") %> prohibited this user from being saved:</h2>

      <ul>
        <% user.errors.each do |error| %>
          <li><%= error.full_message %></li>
        <% end %>
      </ul>
    </div>
  <% end %> 

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

  <div class="field">
    <%= form.label :score %>
    <%= form.number_field :score %>
  </div>
 
  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

这将给你的表单提供适当的字段,以便用户可以输入分数和用户名。在重新启动你的rails服务器后,你可以在localhost:3000/users/new ,查看没有任何样式的应用程序。它看起来像这样。

 view the application

确保你允许新创建的属性通过控制器,用以下代码替换app/controllers/users_controller.rb 中的user_params 方法。

def user_params
      params.require(:user).permit(:username, :score)
end

清理前端

接下来,让我们清理一下索引视图。

app/views/users/index.html.erb ,改变整个标签以匹配以下代码。

  <tbody>
    <% @users.each do |user| %>
      <tr>
        <th>Username</th>
        <th>Score</th>
        <th>Actions</th>
        <th colspan="3"></th>
      </tr>
      <tr>
        <td><%= user.username %></td>
        <td><%= user.score %></td>
        <td><%= link_to 'Show', user %></td>
        <td><%= link_to 'Edit', edit_user_path(user) %></td>
        <td><%= link_to 'Destroy', user, method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <% end %>
  </tbody>

我们现在能够创建、编辑和删除用户。我们还可以查看用户的列表以及他们的分数。我们将通过按分数和降序对列表进行排序来完善这个功能。这是一个小的变化--我们在app/controllers/users_controller.rb 中编辑一行。

现在的索引方法应该是这样的。

def index
  @users = User.all.order("score DESC")
end

这就把被索引视图返回并使用的用户按分数从高到低排序。

你可以在索引视图的路线上,localhost:3000/users ,查看它。页面上会有一个 "新用户 "的链接,你可以按照这个表格创建一些新用户来测试一下这个表。在添加了一些用户之后,索引应该看起来与此类似。

adding new users

为了充分开发这个应用程序,并使其能够愉快地使用,我们将添加一些快速改变分数的功能,并可能添加一些样式。然而,就本教程而言,我们更感兴趣的是CockroachDB如何解决我们的数据库需求,而不是如何编写样式表。

添加CockroachDB

开箱后,为了简单起见,你的Rails应用程序默认使用SQLite 3。让我们来改变它。

首先,在config/database.yml 文件中,将默认标题下的adapter 值改为 "CockroachDB"。默认部分现在应该是这样的。

default: &default
  adapter: cockroachdb
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  timeout: 5000

现在,你需要参考上面的创建CockroachDB无服务器账户部分的连接设置。

首先,你需要下载CockroachDB客户端。你可以在连接窗口中找到下载客户端的命令,如下图所示。

download the client in the connection window

接下来,下载CA证书,这样你的机器就可以通过SSL与数据库安全地对话。

最后,运行提供的命令,从你的终端连接到数据库。如果连接成功,运行exit 命令,退出出现的SQL终端。

虽然你已经下载了SSL证书,但你现在需要让它对你的应用程序可用。

用下面的命令把它复制到你的项目目录。

cp $HOME/.postgresql/root.crt ./root.crt

接下来,用以下代码替换你的config/database.yml 文件的内容。

default: &default
  adapter: cockroachdb
  host: 
  port: 26257
  user: 
  password: 
  database: 
  sslmode: 'verify-full'
  sslrootcert: './root.crt'
  options: "--cluster="
 
development:
  <<: *default
 
production:
  <<: *default

确保把连接窗口中提供的凭证换掉。我们不想在 Git 仓库中存储敏感的凭证,所以使用 Rails 的凭证管理器为我们加密和存储这些凭证是一种常见的最佳做法。然后,我们会用一个环境变量来引用我们需要的信息,如用户名、密码和集群名称。

我们可以使用dotenv库来管理我们的秘密API密钥,但我们将使用Rails最近添加的内置加密凭证管理器来代替。我们放在YAML中的嵌入式Ruby将把秘密拉出来并解密。

首先,你需要在Rails凭证文件中设置访问密钥。

在你的外壳中,运行以下命令来解密,并在Vim中打开凭证文件。

EDITOR=vim bin/rails credentials:edit

让我们为我们要存储的新凭证添加一个部分。

在已经被Vim打开的文件中添加以下代码。

cockroachdb:
  host: 
  user: 
  password: 
  database: 

保存你的修改并关闭Vim。

现在,让我们改变YAML文件中证书的用法,转而使用对Rails证书管理器的调用。

用下面的代码替换你的config/database.yml 文件中的default 部分。

default: &default
  adapter: cockroachdb
  host: <%= Rails.application.credentials.dig(:cockroachdb, :host) %>
  port: 26257
  user: <%= Rails.application.credentials.dig(:cockroachdb, :user) %>
  password: <%= Rails.application.credentials.dig(:cockroachdb, :password) %>
  database: <%= Rails.application.credentials.dig(:cockroachdb, :database) %>
  sslmode: 'verify-full'
  sslrootcert: './root.crt'
  options: "--cluster="

我们的应用现在使用Active Record与CockroachDB无服务器集群对话,这样它就可以存储和检索我们应用所使用的信息。这种设置使我们能够在不同的环境中分享我们的应用数据。

为了测试这一点,我们将把我们的应用程序部署到Heroku。随着我们的应用和数据库都在云中运行,我们将创建一个完全无服务器的应用。

部署应用程序

要部署到Heroku,你首先需要创建一个账户。然后,下载Heroku CLI,这样你就可以通过命令行与Heroku对接。

通过登录Heroku开始你的部署。

从你的终端,运行以下命令。

heroku login

接下来,通过运行以下命令,在Heroku的项目目录中创建一个新的应用程序。

heroku create

Heroku在部署前需要做一些准备。首先,从Gemfile中删除SQLite 3 gem,删除指定它的那一行,然后运行以下命令。

bundle install

如果你在装有Apple Silicon的Mac上编写你的应用程序,当你推送到Heroku时,你可能会得到一个错误,因为你的Gemfile指定的架构会发生冲突。你可以通过运行下面这行来预先阻止这种情况。

bundle lock --add-platform x86_64-linux

接下来,将修改添加到暂存区,提交修改,并通过以下命令将你的应用程序部署到Heroku。

git add .
git commit -a
git push heroku main

如果部署成功,我们的应用程序就几乎可以使用了。虽然它已经上线,但你仍然需要用你在本地拥有的主密钥配置Heroku上的Rails凭证管理器。

主密钥是一个字符串,存储在config/master.key

运行下面的命令来完成配置。

heroku config:set RAILS_MASTER_KEY=

这就重置了你的Heroku服务器。现在应用程序几乎已经启动并运行了。

很可能Heroku已经自动为你的应用程序分配了一个postgres数据库。这将设置DATABASE_URL 环境变量,它将覆盖我们在config/database.yml 中精心选择的值。

为了确认这一点,请在网上登录Heroku并选择你的应用程序。在 "资源"选项卡中,检查Add-ons列表中是否有 "Heroku Postgres "项目。如果你看到一个,通过点击最右边的箭头将其删除。

check for a “Heroku Postgres” item in the <em>Add-ons</em> list

然后,进入Web应用程序的 "设置"选项卡,打开 "配置变量 "部分。如果仍然有一个DATABASE_URL 的条目,将其删除。

 the “Config Vars” section

现在,你的应用程序可以正确地从config/database.yml 摄取数值。做一些你认为合适的小改动--也许是一个代码注释或README--然后提交代码。

然后,通过运行重新部署。

git push heroku main

你可以通过在Heroku提供的URL中添加/users ,并在浏览器中访问它来查看我们创建的用户索引页面。

the user index page

结论

通过学习本教程,你已经建立了一个新的Ruby on Rails应用程序,可以从数据库中创建、读取、更新和删除信息。你将Active Record配置为使用CockroachDB无服务器集群而非SQLite 3,并将该应用部署到Heroku。