質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Active Record

Active Recordは、一つのオブジェクトに対しドメインのロジックとストレージの抽象性を結合するデザインパターンです。

Q&A

解決済

1回答

876閲覧

Rails ForeignKeyの命名規則を変更したい

Nero1129

総合スコア130

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Active Record

Active Recordは、一つのオブジェクトに対しドメインのロジックとストレージの抽象性を結合するデザインパターンです。

0グッド

0クリップ

投稿2022/04/03 14:59

前提

Rails初心者です。

ActiveRecordで名前空間を持ったモデルを参照する際、ActiveRecordが自動認識しているカラム名をInitializeなどで全体的に書き換えたいです。
言葉で伝わりづらいと思うので、コードで説明します。

前提

ruby

1# app/models/content.rb 2module Content 3 def self.table_name_prefix 4 'content_' 5 end 6end 7 8# app/models/content/post.rb 9class Content::Post < ApplicationRecord 10 belongs_to :category 11end 12 13# app/models/content/category.rb 14class Content::Category < ApplicationRecord 15 has_many :post 16end

上記のようなリレーションでjoinを実行した時、発行されるSQL

shell

1$ rails c 2irb(main):001:0>Content::Post.joins(:category).to_sql 3=> "SELECT `content_posts`.* FROM `content_posts` INNER JOIN `content_categories` ON `content_categories`.`id` = `content_posts`.`category_id`"

実現したいこと

今回行いたいのは次のようなテーブルで、リレーションを組みたいです。

ruby

1# db/Schema.rb 2create_table "content_posts", charset: "utf8mb4", force: :cascade do |t| 3 t.string :title, null: false, comment: 'タイトル' 4 t.string :content, null: false, comment: '内容' 5 ############## 問題点 ############## 6 t.bigint :content_category_id, null: false, comment: 'カテゴリID' 7 ############## 問題点 ############## 8 9 t.datetime :deleted_at, comment: "削除日時" 10 t.timestamps null: false, comment: "作成・更新日時" 11end 12 13create_table "content_categories", charset: "utf8mb4", force: :cascade do |t| 14 t.string :name, null: false, comment: 'カテゴリ名' 15 16 t.datetime :deleted_at, comment: "削除日時" 17 t.timestamps null: false, comment: "作成・更新日時" 18end

普通に下記のようにmodelでforeign keyを設定すればいいことなのですが…

ruby

1# app/models/content/post.rb 2class Content::Post < ApplicationRecord 3 belongs_to :category, foreign_key: 'content_category_id' # ここを自動で名前空間を見てPrefixをつけさせたい 4end

ActiveRecordで発行されるSQLの外部キー全体的に名前空間のPrefixをつけたいです。
InitializeだとModel書くたびに再起動しなくてはいけないので、できればapp/models/content.rbなどでオーバーライドする方法などがあればご教授いただけると幸いです。

補足情報(FW/ツールのバージョンなど)

Ruby on Rails 6

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

winterboum

2022/04/03 16:04

疑問 belongs_to :category, foreign_key: 'content_category_id' これで動かしてみましたか? エラーなるのではと。 Content::Category ではなく、Category を探しに行って、「ないよ」と。
Nero1129

2022/04/04 00:26

即興で作ったのでリレーションがおかしいのは悪しからず。 単に伝わればいいと思い、書きましたので… 質問の趣旨とは関係ないので、修正しません。
winterboum

2022/04/04 00:32

やりたいことは理解できますが、前提が伝わらないのです。 belongs_to :category, foreign_key: 'content_category_id' でうごかないとすると belongs_to :category, class_name: Content::Category とか belongs_to :contents_category とか にする必要があります。 後者にすれば 自動的に foreign_key: 'content_category_id' ですし 動くものを示して、で そこのどこを直したいのか、という形にできませんか
Nero1129

2022/04/04 02:22

動くものでということでしたので、今、実際に上記にコードでSQLを発行できるか確認してきました。 ■ ForeignKeyを明示してない状態 ``` shell irb(main):001:0> Content::Post.joins(:category).to_sql => "SELECT `content_posts`.* FROM `content_posts` INNER JOIN `content_categories` ON `content_categories`.`id` = `content_posts`.`category_id`" ``` ■ ForeignKeyを明示してる状態 ``` shell irb(main):001:0> Content::Post.joins(:category).to_sql => "SELECT `content_posts`.* FROM `content_posts` INNER JOIN `content_categories` ON `content_categories`.`id` = `content_posts`.`content_category_id`" ``` ■ ForeignKeyを明示せず、:content_category, :content_postとした時 ``` shell irb(main):001:0> Content::Post.joins(:category).to_sql Traceback (most recent call last): /usr/local/bundle/gems/activerecord-6.1.4.6/lib/active_record/associations/join_dependency.rb:221:in `find_reflection': Can't join 'Content::Post' to association named 'category'; perhaps you misspelled it? (ActiveRecord::ConfigurationError) irb(main):002:0> Content::Post.joins(:content_category).to_sql Traceback (most recent call last): /usr/local/bundle/gems/activerecord-6.1.4.6/lib/active_record/inheritance.rb:237:in `compute_type': uninitialized constant Content::Post::ContentCategory (NameError) ``` class_nameの検証はForeignKeyを明示してるのと同じなので行なっていません。 :content_category, :content_postでできるのであればと思いましたが、できなかったので、やはり、InitializeがnamespaceでPrefixを付ける方法が知りたいです。
winterboum

2022/04/04 04:37

明示しないでうごくのでしたら、それでよいのでは?
Nero1129

2022/04/04 14:45

> :content_category, :content_postでできるのであればと思いましたが、できなかったので、やはり、InitializeがnamespaceでPrefixを付ける方法が知りたいです。 動かないと書いたのですが…
winterboum

2022/04/05 14:45

ForeignKeyを明示してない状態 ではうごいたのですよね?
Nero1129

2022/04/06 07:00

発行されるSQLが間違ってて動いてません。 > ■ ForeignKeyを明示してない状態 > ``` shell > irb(main):001:0> Content::Post.joins(:category).to_sql > => "SELECT `content_posts`.* FROM `content_posts` INNER JOIN `content_categories` ON `content_categories`.`id` = `content_posts`.`category_id`" > ``` ForeignKeyを明示してない状態で`content_category_id`を発行して欲しいと質問で書きました。 ``` SQL SELECT `content_posts`.* FROM `content_posts` INNER JOIN `content_categories` ON `content_categories`.`id` = `content_posts`.`content_category_id` ```
guest

回答1

0

ベストアンサー

長々と引きずったのは、私の知る限りでは「そういうことを公式にサポートしている」という情報がないので、
やるとすると結構ハードになって、それだったら foreign_key 使う方がよほど楽
ということになるかな、、、と思ったので、
今回ちと調べたところ、 class名の :: を table名の _ に変えることはしてますが、逆がなかったですね。
で、
やるとすると
ARのModule ActiveRecord::Associations::ClassMethods をハックしてforeign_key解決部分を見つけ出す
ARを継承する class 仮称 ActiveRecordNewをつくって、それを overrideする
そして
class Content::Post < ApplicationRecordNew でMODEL定義する

でしょうか。

投稿2022/04/06 08:40

winterboum

総合スコア23284

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問