RubyプロダクトをElixirプロダクトへリプレイスする作業を自動化しよう① fukuoka.ex Elixir/Phoenix Advent Calendar 2020【5分で読める】
この投稿は『fukuoka.ex Elixir/Phoenix Advent Calendar 2020』の19日目の記事です。
qiita.com
また、この投稿は、先日のElixir Digitalization Implementors #3 でLT発表させてもらった内容と一部重複しています。
fukuokaex.connpass.com
解説
前述のrtoeは既存のRubyプロダクトのmigrationファイルを読み込み、
ElixirプロダクトでSchemaを生成するコマンドを生成するものです。
一部抜粋して解説します。
基本的にこんなことをやっています。
- Rubyプロダクトのmigrationファイルを読み込む
- 読み込むんだ下記の文字列を加工
- テーブル名
- カラム名
- カラムの型
これがメインとなるメソッドです。
defmodule Mix.Tasks.Schema do @moduledoc "Printed when the user requests `mix schema migration_file_path`" @shortdoc "Migration file argument" use Mix.Task @impl Mix.Task def run(file) do {:ok, contents} = File.read(file) lines = String.split(contents, "\n") table = lines |> get_table_name class = lines |> get_class_name columns = lines |> get_columns elements = [ "mix phx.gen.schema Context.#{class}", "context_#{table}", columns ] Mix.shell().info(Enum.join(elements, " ")) end defp get_table_name(lines) do line = lines |> line_containing_word("create_table") case Regex.named_captures(~r/^create_table :(?<tn>.*) do |t|$/, "#{line}") do nil -> "" %{"tn" => table_name} -> table_name end end defp get_class_name(lines) do line = lines |> line_containing_word("class Create") case Regex.named_captures(~r/^class Create(?<cn>.*)s < ActiveRecord::Migration$/, "#{line}") do nil -> "" %{"cn" => class_name} -> class_name end end defp get_columns(lines) do lines |> Enum.filter(&is_column(String.trim("#{&1}"))) |> Enum.map(fn str -> String.trim(str) end) |> Enum.map(fn str -> get_column_type(str) end) end defp get_column_type(str) do lc = String.split(str, ", ") [head | _] = lc case Regex.named_captures(~r/^t.(?<type>.*) :(?<col>.*)$/, "#{head}") do nil -> "" %{"type" => type, "col" => col} -> "#{col}:#{type} " end end defp is_column(line) do case Regex.named_captures(~r/^t.*$/, "#{line}") do nil -> false %{} -> true end end def line_containing_word(lines, word) do lines |> Enum.find(&String.contains?("#{&1}", word)) |> String.trim() end end
最後に適切なmix phx.gen.schemaコマンドを生成してくれます。
実際に
プロジェクトでも使っていて、
手作業でElixirのSchemaを実装する場合に比べてカラム名や型のミスもなくなりました。
今後
rtoeに関して、Elixir Digitalization Implementors #3 で頂いた下記のフィードバックも今後やりたいです。
- CLI化 →releaseしました。(2020/12/28更新)
また、Elixirへのリプレイスに関してどんなプロジェクトでも行う共通の工程があると思うのですが、できればそこを自動化していきたいです。
ちょっと短めですが、失礼いたします。