1つのRails上に複数アプリを載せようと思って、アプリごとにサブディレクトリを切って格納していたところ、1対多の紐づけ設定のところでNameErrorが出てきて困った。アソシエーションでclass_nameを追記したら直った。
Agenda
やりたいこと
1つはptという名前でアプリを作りたい。たとえばこんな感じ。
/app/controllers/pt/events_controller.rb
/app/controllers/pt/trainers_controller.rb
/app/models/pt/trainer.rb
/app/models/pt/event.rb
もう1つはnoteという名前でアプリを作りたい。
/app/controllers/note/books_controller.rb
/app/models/note/book.rb
Sacaffold
ディレクトリを切る場合は、「::」をつける。
$ rails g scaffold pt::trainer name:string birthdate:date sex:integer email:string title:string comment:text area:string
$ rails g scaffold pt::event name:string the_date:date title:string comment:text area:string pt_trainer:belongs_to
アソシエーション
ptアプリ(失敗例)
Pt::Trainer 1-n Pt::Event
# /app/models/pt/trainer.rb
class Pt::Trainer < ApplicationRecord
has_many :pt_events # <- NameError uninitialized constant Pt::Trainer::PtEvent
end
# /app/models/pt/event.rb
class Pt::Event < ApplicationRecord
belongs_to :pt_trainer # <- NameError uninitialized constant
end
エラー内容
これでevent側にデータ登録すると、NameErrorが出る。
NameError in Pt::EventsController#create
uninitialized constant Pt::Event::PtTrainer
また、trainer側でhas_manyのアソシエーションでデータ取得しようとすると同様のエラーが出る。(たとえば、rails consoleで「Pt::Trainer.all.includes(:pt_events)」と実行)
ptアプリ(成功例)
以下のように指定することで解決。
# /app/models/pt/trainer.rb
class Pt::Trainer < ApplicationRecord
#has_many :pt_events # <- NameError uninitialized constant Pt::Trainer::PtEvent
#has_many :pt_events, class_name: 'Pt::Event' # <- SQLite3::SQLException: no such column: pt_events.trainer_id: SELECT "pt_events".* FROM "pt_events" WHERE "pt_events"."trainer_id" IN (?, ?)
has_many :pt_events, class_name: 'Pt::Event', foreign_key: :pt_trainer_id
end
# /app/models/pt/event.rb
class Pt::Event < ApplicationRecord
#belongs_to :pt_trainer # <- NameError uninitialized constant
belongs_to :pt_trainer, class_name: 'Pt::Trainer'
end