環境
- Rails 7
Railsのモデルディレクトリ荒れる問題
Railsはデフォルトだとapp/modelsにモデルファイルを生成する。
それはルールなので別にいいのだが、プロジェクトが成長するに従って10ならいいが50を超えてくるとかなりキツくなる。
そこでディレクトリをapp/models以下に作成して階層化したい。ディレクトリ別にグルーピングしたい
が、ググってもDB構造の階層化ばかりでフォルダを分ける記事が全然見当たらなかったのでメモ
サブディレクトリ化していない例
例えばこれは通常のPostモデル app/models/post.rb
class Post < ApplicationRecord end
.model_name
でそのモデルの命名規則などがわかる
irb(main):014:0> Post.model_name => <ActiveModel::Name:0x0000000114a6d2f8 @collection="posts", @element="post", @human="Post", @i18n_key=:post, @klass=Post (call 'Post.connection' to establish a connection), @name="Post", @param_key="post", @plural="posts", @route_key="posts", @singular="post", @singular_route_key="post", @uncountable=false>
まあそうなるわな
サブディレクトリ化する
まずは app/models/admin.rb を作成して以下
module Admin end
で app/models/admin/post.rb を作成して以下
class Admin::Post < ApplicationRecord end
これだけで後は Admin::Post
でアクセス出来る
irb(main):021:0> Admin::Post.new (0.1ms) SELECT sqlite_version(*) => #<Admin::Post:0x0000000115264830 id: nil, title: nil, date: nil, body: nil, created_at: nil, updated_at: nil>
だがこれだけではめでたしめでたしとはならない。form_withでフォームを作成するともれなくURLが想定ではなくなってバグるため。
もともとPost
を Admin::Post
にディレクトリ作っただけなので、ルーティングやコントローラー周りは階層化するつもりはない。
しかし同様に .model_name
すると route_key が「admin_posts」になってしまってるじゃないか。。。
irb(main):014:0> Post.model_name => <ActiveModel::Admin::Post:0x00000001141bd180 @collection="admin/posts", @element="post", @human="Post", @i18n_key=:"admin/post", @klass=Admin::Post (call 'Admin::Post.connection' to establish a connection), @name="Admin::Post", @param_key="admin_post", @plural="admin_posts", @route_key="admin_posts", @singular="admin_post", @singular_route_key="admin_post", @uncountable=false>
解決方法
app/models/admin.rb にメソッドを追加する
module Admin def self.use_relative_model_naming? true end end
でRailsをリロードすると route_key
が posts
に戻っている!
irb(main):023:0> Admin::Post.model_name => <ActiveModel::Name:0x0000000117305ee0 @collection="admin/posts", @element="post", @human="Post", @i18n_key=:"admin/post", @klass=Admin::Post (call 'Admin::Post.connection' to establish a connection), @name="Admin::Post", @param_key="post", @plural="admin_posts", @route_key="posts", @singular="admin_post", @singular_route_key="post", @uncountable=false, @unnamespaced="Post">
他にも色々見えないところで変わってるらしく、ただモデルの場所をフォルダ分け考えているなら全然あり
備考
ちなみにRailsのモデルを階層化しろって話はRails1.2時代から指摘されてたっぽい。ウケる