Skip to content

Instantly share code, notes, and snippets.

@funwarioisii
Created October 24, 2022 10:47
Show Gist options
  • Save funwarioisii/2a9fa5f3f782c3752612887ccbd7c5fc to your computer and use it in GitHub Desktop.
Save funwarioisii/2a9fa5f3f782c3752612887ccbd7c5fc to your computer and use it in GitHub Desktop.

speek という gem をリリースしてみた

speek という gem をリリースしてみたという記事です。

なにができるのか

users.schema のようなテーブル定義からモデルファイルの型定義を出力します。 ターミナルでの入力例はこんな感じです。

% gem install speek  
Fetching speek-0.1.1.gem
Successfully installed speek-0.1.1
Parsing documentation for speek-0.1.1
Installing ri documentation for speek-0.1.1
Done installing documentation for speek after 0 seconds
1 gem installed

% cat example/schema/users.schema 
create_table "users", id: :bigint, unsigned: true, force: :cascade, options: "ENGINE=InnoDB" do |t|
  t.string "name", null: false
  t.text "desc", null: true
  t.datetime "deleted_at"
  t.integer "weight", null: false, default: 0, unsigned: true
  t.boolean "is_banned", null: false, default: false

  t.timestamps
end

% speek -i example/schema/users.schema -s rbs
class User
  attr_accessor id: Integer
  attr_accessor name: String
  attr_accessor desc: (String | nil)
  attr_accessor deleted_at: (Time | nil)
  attr_accessor weight: Integer
  attr_accessor is_banned: Boolean
  attr_accessor created_at: Time
  attr_accessor updated_at: Time
end

背景や動機

単純に AST を操作してなんかやるというのをやってみたかったから、gemをリリースしてみたかったから。というのが個人的な動機ですが…

Ruby には型がないから書きたくないという人がいると聞きますが、近年は rbs という仕組みがあり、 steep という gem や IDE などでいくらか型の恩恵に授かる機会が増えました。

一方で rbs ファイルをアプリケーションのコードとは別に作成し、管理するのは気が滅入る作業です。 動いているシステムの歴史がながければ長いほど、この手間は大きいです。 なんとか既存の資産を活かして rbs を生成したいという気持ちがありました。

自分の所属しているチームでは Rails を使っていて、 ridgepole という gem を使いテーブル定義(schema)を管理しています。 そしてこの schema に対応するモデルが存在していますが、型定義はなかったりします。 そこで、 schema の抽象構文木を利用することでモデルに対応する型定義を出力する gem を作ってみたという感じです

speek コマンドについて

speek では3つのオプションを指定することが出来ます

  • -i:input_file_path : 入力とする schemafile のパスを指定するオプション
  • -o:output_file_path : 出力先のファイルパスを指定するオプション。指定がなければ標準出力される
  • -s:schema_type : 出力する型定義の種類

やや命名でミスった感じがあるので直したいとは思っているのですが、いまはこんな感じです。

-s:schema_type では rbs の他に GraphQL の型も生成できるようにしています。 先程の出力する型を GraphQL 風にしてみると

% speek -i example/schema/users.schema -s gql
type User {
  id: Int!
  name: String!
  desc: String
  deletedAt: String
  weight: Int!
  isBanned: Boolean!
  createdAt: String!
  updatedAt: String!
}

のようになり、API モードで作成した graphql-rails を使っているようなプロジェクトでも使えるのではないでしょうか。

個人的に開発しているプロダクトで色々使っていき、便利にしていこうと思っています

今後の予定

GraphQL の Custom Scalars に対応したり protobuf の出力もしたいなぁなどと思っています

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment