我的 Ruby 任务自动化初体验(22 行代码)
由 Mux 赞助的 DEV 全球展示挑战赛:展示你的项目!
少数了解我代码的人都知道,我主要专注于前端:HTML、CSS、JavaScript(可惜)、无障碍设计,以及其他任何让同事头疼的问题。我几乎每次接触后端语言,比如 Ruby,都是直接或间接出于工作需要,而非出于自愿。
昨天那一个小时之所以如此特别,是因为这一切都让我印象深刻。那是我第一次真正迸发出用 Ruby 解决问题的灵感。而且,那还是一个自动化问题,这在 Gulp 等功能较为有限的工具之外,我从未尝试过。
虽然这只是一次小小的胜利,但它确实缓解了我常见的职业焦虑。所以我认为有必要分享一下我是如何解决这个问题的,以及为什么它对我意义如此重大。
问题
我不打算赘述背景,但基本问题是:
- 我有几个包含 front matter 的 markdown 文件,以及一个包含类似数据的长 YAML 文件。
- 我希望将每个 YAML 条目转换为具有正确名称和数据的 Markdown 文件。这样,就可以按时间顺序循环处理它们,供某个网站生成器使用。
我的第一个想法是手动完成这项工作——创建所有 Markdown 文件并重命名,复制所有数据,重复编写通用代码,根据需要调整数据等等。我的第二个想法是:“这不正是编程应该避免的吗?”
我记得有个同事说过 Ruby 可以处理基本的文件操作和创建。我意识到这是个绝佳的机会来检验这一点,更重要的是,看看我是否能理解它。
自动化系统必须做什么
作为参考,YAML 文件内容如下:
- articles:
- name: You Can Be a Casual Blogger
date: "2018-11-05"
link: https://dev.to/maxwell_dev/you-can-be-a-casual-blogger-ff0
description: Seeing so many professional writers emerge on Dev.To has helped me see, and accept, my casual blogger habits.
...etc
该 Ruby 脚本需要完成以下几项任务:
1) 导入 YAML 数据
2) 遍历 YAML 数据
3) 根据数据创建文件名
4) 为文件的 front matter 创建多行字符串
5) 将其保存到新文件中
最终生成的 Markdown 文件如下所示:
---
title: "You Can Be a Casual Blogger"
date: "2018-11-05"
external: true
link: "https://dev.to/maxwell_dev/you-can-be-a-casual-blogger-ff0"
excerpt: "Seeing so many professional writers emerge on Dev.To has helped me see, and accept, my casual blogger habits."
---
它们还会像这样,带有日期和标题的名称:
2018-11-05-you-can-be-a-casual-blogger.md
我原本以为会遇到一些障碍然后放弃。结果,只用了35分钟,写了22行就完成了!
找到解决方案
1)导入 YAML 数据
原来 Ruby 内置了一个 YAML 模块,无需安装任何 gem。稍微搜索一下就很快找到了使用方法。
require 'yaml'
data = YAML.load_file('articles.yml');
2) 遍历 YAML 数据
由于数据格式复杂,遍历这些数据非常棘手,这可能是我编写 YAML 的方式造成的。导入的数据基本上是一个数组,它嵌套在一个对象中,而对象又嵌套在另一个数组中。这简直就是 YAML 嵌套,真希望莱昂纳多·迪卡普里奥能来客串一下。
解决这个问题不需要进入炼狱,只需要一些反复尝试。
data.each do |articles|
articles['articles'].each do |article|
# Code goes here!
end
end
3)根据数据创建文件名
每个 YAML 条目都需要根据日期和标题指定一个特定的文件名。这需要两个步骤:
- 将每个字符串转换为所需的格式。
- 标题需要全部小写,并且用短横线代替空格。
- 日期无需更改。
- 每个字符串都必须插入到文件名、扩展名以及文件路径中。
两个变量之后,我需要的一切都在变量中了file_name。
titlized_name = article['name'].downcase.gsub!(/\s+/, '-')
file_name = "./../_posts/#{article['date']}-#{titlized_name}.md"
4) 为文件的前置元数据创建多行字符串
这让我费了些功夫才找到,但我找到了%Q一个用于创建带插值的多行字符串的简写(或者说正是我需要的)。
缺点是它破坏了代码的对齐和可读性,最终结果会体现出来。但我仍然觉得它足够简洁易读,值得一试。
front_matter = %Q(---
title: "#{article['name']}"
date: "#{article['date']}"
external: true
link: "#{article['link']}"
excerpt: "#{article['description']}"
---
)
5)将此文件另存为新文件
实际上,我在开始做任何事情之前就发现了这一点。
谷歌搜索我仔细研究了各种方案。Ruby 提供了一个非常简单的文件创建、写入和保存功能。我只需要把编译好的代码全部导入到File对象中,它就能正常工作了。
out_file = File.new(file_name, "w")
out_file.puts(front_matter)
out_file.close
问题已解决!
以下是最终的 22 行脚本!
# convert_data.rb
require 'yaml'
data = YAML.load_file('articles.yml');
data.each do |articles|
articles['articles'].each do |article|
titlized_name = article['name'].downcase.gsub!(/\s+/, '-')
file_name = "./../_posts/#{article['date']}-#{titlized_name}.md"
front_matter = %Q(---
title: "#{article['name']}"
date: "#{article['date']}"
external: true
link: "#{article['link']}"
excerpt: "#{article['description']}"
---
)
out_file = File.new(file_name, "w")
out_file.puts(front_matter)
out_file.close
end
end
我保存了文件,屏住呼吸,然后跑了出去ruby convert_data.rb。一秒钟后,我的_posts目录里就出现了所有需要的文件,命名也正确无误。
考虑到这花费的时间(以及它还有很大的改进空间),我总体上并没有节省多少时间。但是写作过程更有趣,也更轻松,所以从效率的角度来看,最终还是有所收获!
感到充满希望
有些人可能会好奇,为什么我写了一个相对简单的 Ruby 脚本就这么高兴。一部分原因是我习惯庆祝小小的胜利,另一部分原因则与我作为一名开发者长期以来存在的某种不安全感有关。
这种不安全感在我与另一位开发人员共同主持的一次职业日活动中得到了很好的体现。我们的专长截然不同——我负责用户界面和无障碍设计,他负责任务自动化和数据处理。
虽然我们俩都受到了学生们的热烈欢迎,但他的编程风格似乎更能引起共鸣。自动化通常是编程技能中最受重视的(正如他告诉孩子们的那样,自动化带来的收入也更高)。这种对几乎所有自动化都格外重视的态度,总是让我对自己专注于前端开发感到不安。我热爱前端开发,但像那次职业日一样的经历,仍然让我对自己的职业前景感到焦虑。
这个 Ruby 脚本是我第一次真正体验到任务自动化,虽然规模很小。它不是从别处复制的,也不是简单的前端资源自动化。它是我自己写的,节省了很多人原本会浪费的时间和精力。看到自己完成这一切,也稍微缓解了我对职业生涯的不安全感。
最重要的是,这表明我可以在这里不断提升技能。我可以负责前端开发,同时根据需要自动化那些枯燥乏味的工作。任务自动化让我感觉更像一个真正的程序员——高效、懒散、务实,而且无比得意。
它可以帮助我消除这种职业上的不安全感,一次写一个小剧本。
文章来源:https://dev.to/maxwell_dev/my-first-taste-of-ruby-task-automation-in-22-lines-3gib