railsでクラス名を取得して、さらにスネークケースに変換するときの方法。

たとえば、viewファイルでidやname属性あたりを指定するときにひとつだけselect_tagなんかでレールから外れた(そうせざるおえない)フォーム項目を使っていると使いたくなるときがあります。

以下のようなクラスがあったとします。

module Samples
  class Hello
    # 略
  end
end

nameメソッドを使うと以下のような感じでクラス名を取得できるんだけど、キャメルケースの文字列が手に入ります。

irb(main):004:0> Samples::Hello.name
=> "Samples::Hello"
irb(main):005:0> Todos::CreateForm.name.camelize
=> "Todos::CreateForm"
irb(main):006:0> Todos::CreateForm.name.underscore
=> "todos/create_form"

これをスネークケースに変換したい!スネークケースへの変換はunderscoreメソッドを使うと可能です。

キャメルケースに変換するのはcamelizeなので、snakelaizeとか、そんな名前かと思ったら違いました。

irb(main):006:0> Samples::Hello.name.underscore
=> "samples/hello"

ただ、モジュールとクラス名の間がスラッシュになってしまいます。これもアンダースコアに変換したい。

ということで、gsubでスラッシュを変換しました。

irb(main):006:0> Samples::Hello.name.underscore.gsub('/', '_')
=> "samples_hello"

ちなみに、インスタンスからクラス名を取得するときは.class.nameとすれば取得できます。

このメソッドはmoduleに切り出して使うのが良さそうです。

irb(main):008:0> t = Samples::Hello.new
irb(main):009:0> t.class.name.underscore.gsub('/', '_')
=> "samples_hello"

こうした文字列をいろんな書き方に変換してくれるメソッドは以下のような感じでactivesupportのソースコードにまとまって書いてありました。

これと、Rubyのメソッドを調べてみて、必要なメソッドはないかを確認、なかったら自分で作るとかがよさそう。

ソースコードはこんな感じ

ソースコードのコメントがとてもわかりやすいので、コメントだけでもみる価値ありですね。大変素晴らしい。

# The reverse of +camelize+. Makes an underscored, lowercase form from the expression in the string.
#
# +underscore+ will also change '::' to '/' to convert namespaces to paths.
#
#   'ActiveModel'.underscore         # => "active_model"
#   'ActiveModel::Errors'.underscore # => "active_model/errors"
#
# See ActiveSupport::Inflector.underscore.

この記事の環境情報

  • rails 7.0.4