我如何用几十行 Ruby 代码替换 Rails 应用

2025-06-10

我如何用几十行 Ruby 代码替换 Rails 应用

几年前,我弄坏了工作时的一个仪表板。

作为构建新功能的一部分,我更改了数据库架构。我精心制定了添加新列和迁移现有数据的计划。我确保对数据库的更改能够兼容新旧应用程序代码,并且该功能可以在不停机的情况下部署。

我忘了考虑一下,我们的应用程序并非数据的唯一消费者。我们的数据团队维护着公司用来指导产品决策和财务预测的仪表板。这些仪表板要求我们的数据库模式保持特定的样子,而当我未经数据团队许可就进行更改时,其中一个仪表板就崩溃了。

修复完仪表盘后,我开始思考如何避免将来犯同样的错误。我决定每次修改数据库架构时都要提醒自己。为了获得提醒,我找到了最熟悉的工具,并启动了一个新的 Rails 应用。

Rails 应用有很多功能

我开发DiffAlert应用的目的是,每当有人对我们公司应用程序的分支进行更改时,都会向 Slack 发送警报。我发现 GitHub 有db/structure.sqlwebhook 并且推送事件会发送提交数据,包括哪些文件被更改了。master

几个小时后,我启动了应用程序,为 GitHub webhook 事件创建了一个端点,并编写了代码来判断db/structure.sql推送中是否有变化。DiffAlert 的核心逻辑已经完成。接下来,真正的工作开始了。

接下来,我必须弄清楚如何向 Slack 发送警报。我们已经在使用Slack 的电子邮件应用,所以我注册了一个新的Mailgun帐户,并使用Action Mailer创建了一个电子邮件模板。然后,我需要在某个地方部署 DiffAlert,所以我创建了一个新的Heroku应用程序,并进行了一些调整,以确保所有内容都与我的工作流程正确配置。

此外db/structure.sql,我们还想监控代码库中的其他一些文件,所以我开始构建一个 UI 来配置警报设置。我需要身份验证,所以我设计了数据模型并创建了登录和注册表单。然后,我需要另一个视图来显示所有警报,还需要表单来创建新警报和编辑现有警报。我需要后台任务,以便像 Webhook 解析和电子邮件发送这样耗时的操作不会阻塞常规的 Web 请求。

DiffAlert 用户界面

DiffAlert 运行了大约一年半,每当数据库架构发生变更时,它都会在 Slack 上提醒我的团队。每次我们都会联系数据团队,这样就再也没有损坏任何仪表盘了。

DiffAlert 是一个副项目,所以当我离开公司时,他们需要决定是继续向离职员工发送他们的 GitHub 元数据,还是维护他们自己的 DiffAlert 实例,或者停止接收警报。他们理所当然地决定停止接收警报。

GitHub Actions 帮助我集中精力解决问题

我在 GitHub 工作,当我了解到GitHub Actions时,我就想着能不能用一个 Action 来替代 DiffAlert。GitHub Action 是用任意语言编写的代码,当仓库中发生指定事件时,它会在 Docker 容器中运行。我发现推送事件可以触发 GitHub Action 工作流。我还发现有一个 GitHub Action可以向 Slack 发送消息。于是我开始编写“修改文件过滤器”

首先,我需要一个Dockerfile。我想用 Ruby 编写我的 Action,所以我按照说明从官方 Ruby 基础镜像FROM创建 Docker 容器。我编写了一些说明,以便我的 Action 能够在 GitHub Actions 可视化工作流编辑器中正确显示。最后,我指定了 Docker 容器需要访问的文件夹,并将 指向一个可执行的 Ruby 脚本。LABELENTRYPOINT

# Dockerfile

FROM ruby:2.6.0

LABEL "com.github.actions.name"="Modified File Filter"
LABEL "com.github.actions.description"="Stops a workflow unless a specified file has been modified."
LABEL "com.github.actions.icon"="filter"
LABEL "com.github.actions.color"="orange"

ADD bin /bin
ADD lib /lib

ENTRYPOINT ["entrypoint"]
Enter fullscreen mode Exit fullscreen mode

可执行的 Ruby 脚本将大部分工作委托给一个普通的 Ruby 类,PushEvent该类解析来自 GitHub 的事件数据,并判断特定路径下的文件是否被修改。当推送事件修改文件时,该操作会退出并返回一个0状态,以触发工作流中的下一个操作。当推送事件未修改文件时,该操作会退出1并暂停工作流。

# bin/entrypoint

require_relative "../lib/push_event"

file_path = ARGV.first
push_event = PushEvent.new(File.read(ENV.fetch("GITHUB_EVENT_PATH")))

if push_event.modified?(file_path)
  puts "#{file_path} was modified"
  exit(0)
else
  puts "#{file_path} was not modified"
  exit(1)
end
Enter fullscreen mode Exit fullscreen mode

我不需要配置电子邮件,也不需要弄清楚如何与 Slack 集成,因为我可以依赖现有的 GitHub Action for Slack。我不需要设计任何 UI 或身份验证,因为这些都由 GitHub 处理。我不需要配置数据库或后台作业。我不需要启动 Heroku 应用程序并设置部署。

GitHub Actions 工作流编辑器中修改的文件过滤器

从小处着手

Rails 以其出色的验证想法的框架而闻名。你可以在 15 分钟内用 Rails 搭建一个博客!因为我热爱使用 Rails,所以每当我有想法时,我通常都会首先想到它。

但即使 Rails 提供了所有这些神奇的功能,大多数应用仍然需要一堆东西——比如身份验证、UI、后台任务、邮件发送、部署——这些功能并非我独有。下次我有新想法时,我会寻找编写更少代码、维护更少基础设施的方法,至少在起步阶段是这样。

封面图片由 Iain Farrell 在Flickr上提供。

鏂囩珷鏉ユ簮锛�https://dev.to/nholden/how-i-replaced-a-rails-app-with-a-few-dozen-lines-of-ruby-3l1m
PREV
尝试以失败告终今天,为明天的美好开始
NEXT
使用具有独立 Angular 功能的 NgRx 包