Railsのアソシエーションにて親モデルと子モデルの紐付けはインスタンス配列で参照できます。 アソシエーションの設定を行った後ならば、このインスタンス配列自体で削除や追加を行うと、Railsが自動的に紐付け(外部キーに親モデルのidを入れる)を行ってくれます。
# report.rb class Report < ApplicationRecord has_many :comments ... end # comment.rb class Report < ApplicationRecord belongs_to :report ... end
r1 = Report.find(1) comments_at_r1 = r1.comments puts comments_at_r1 #=> [#<Comment:0x000... id: 1, ...>, #<Comment:0x000... id: 2, ...>, <Comment:0x000... id: 3, ...>] # この配列に追加したり削除したりすることで紐付けを行なってくれる。 new_comment = Comment.new(content: "test") comments_at_r1 << new_comment #外部キーに自動でreport_id: 1を入れてくれる!
しかし、そのインスタンス配列はクラスはArray
ではありません。ActiveRecord::Associations::CollectionProxy
です。
なので、Array
では使えるけど、ActiveRecord::Associations::CollectionProxy
では使えないメソッドがあります。
delete_at
とかdelete_if
とかはダメ。(他の候補挙げてくれるので優しい)
comments_at_r1.delete_at(1) #=> `method_missing': undefined method `delete_at' for #<ActiveRecord::Associations::CollectionProxy ... #Did you mean? delete_all delete delete_by
あれ、と思ったらクラスを確認したり、methods
メソッドで使えるメソッドを確認しよう!というのが今回の気づきです。
irb(main):010:0> mentions.class => Mention::ActiveRecord_Associations_CollectionProxy irb(main):011:0> mentions.class.superclass => ActiveRecord::Associations::CollectionProxy irb(main):012:0> mentions.class.superclass.superclass # 全部見るならancestorsの方が便利? => ActiveRecord::Relation irb(main):013:0> mentions.class.superclass.superclass.superclass => Object irb(main):0014:0> mentions.methods => [:strict_loading_value=, :create_with!, :from!, :distinct_value=,...