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

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

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

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

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

Active Record

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

Q&A

解決済

2回答

1007閲覧

【ruby】親モデルオブジェクト.子モデルオブジェクト.delete_atメソッドが使えない【Rails】

nobinobinontan

総合スコア18

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

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

Active Record

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

0グッド

2クリップ

投稿2019/02/07 15:41

###no method errorになってしまう

環境
cloud9
rails4.2.8
Mqsql2 0.3.18'
ruby 2.5.3

以下の様にPostテーブル(親)とPosttools(子)テーブルでアソシエーションを組んでいる。

class Post < ActiveRecord::Base has_many :posttools, dependent: :destroy accepts_nested_attributes_for :posttools ,allow_destroy: true end class Posttool < ActiveRecord::Base belongs_to :post belongs_to :tool end

###Postインスタンス.Posttoolsインスタンスの時に、配列の要素を消したい・・・ができない

[1] pry(#<PostsController>)> @post => #<Post:0x00000006831548 id: nil, user_id: 1, title: "なんということだ", created_at: nil, updated_at: nil, likes_count: 0, comments_count: 0, youtube: "", series: nil, unread: 0> [2] pry(#<PostsController>)> @post.posttools => [#<Posttool:0x0000000680baa0 id: nil, post_id: nil, tool_id: 1, created_at: nil, updated_at: nil>, #<Posttool:0x00000006808aa8 id: nil, post_id: nil, tool_id: nil, created_at: nil, updated_at: nil>, #<Posttool:0x00000006801f28 id: nil, post_id: nil, tool_id: nil, created_at: nil, updated_at: nil>]

@postの下にPosttoolsのモデルオブジェクトを配列で複数入れて@post.saveでテーブルにレコードを作っています。

この時、tool_idがnilの時は、そのオブジェクト(要素)だけ消したいのですが
(ここで言うと <Posttool:0x00000006808aa8 id: nil, post_id: nil, tool_id: nil, created_at: nil, updated_at: nil>,
<Posttool:0x00000006801f28 id: nil, post_id: nil, tool_id: nil, created_at: nil, updated_at: nil>] この2つ)

[23] pry(#<PostsController>)> @post.posttools.delete_at(1) NoMethodError: undefined method `delete_at' for #<Posttool::ActiveRecord_Associations_CollectionProxy:0x00000005eec7f8> Did you mean? delete_all delete from /usr/local/rvm/gems/ruby-2.3.1/gems/activerecord-4.2.8/lib/active_record/relation/delegation.rb:136:in `method_missing'

no methoderrorになってしまいます。

###どうすればよいのか

そもそも他のcompact!などのメソッドも使用できず、調べて使用できるメソッドを表示したらこんな感じでした。

[14] pry(#<PostsController>)> @post.posttools.methods => [:method_missing, :<<, :==, :empty?, :length, :size, :to_ary, :to_a, :new, :include?, :find, :count, :select, :first, :any?, :take, :replace, :clear, :concat, [15] pry(#<PostsController>)> a = []

ということはこれしか使えない?

delete_atのソースを調べてposttools.rbに書こうともしたけど正直よくわかりませんでした。

どうすればよいでしょうか?

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

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

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

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

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

guest

回答2

0

@post.posttoolsは、クラスがPosttool::ActiveRecord_Associations_CollectionProxyと出ているように、配列ではありません。そして、これはデータベースから引いてきたそのままになっているので、追加以外の破壊的変更もできません

したいことは、以下2つのどちらでしょうか。

  • データベースからも消したい場合は、@post.posttools[番号].destroyのように1つずつdestroyするか、whereで絞り込んでdeleteするなどしてください。
  • Rails上で削減したリストを得たいのであれば、.to_aで配列に変えてから.delete_atなど好きに操作してください。

投稿2019/02/08 01:05

maisumakun

総合スコア145184

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

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

nobinobinontan

2019/02/08 13:37

丁寧に回答して頂きありがとうございました。 僕の質問の仕方が悪かったのか1番目の方法では削除できず、 mark_for_destructionというメソッドをpost.rbのコールバック内で使用したら削除することができました。
guest

0

自己解決

post.rbに以下の様にコールバック内にmark_for_destructionというメソッドを使用したら削除できた。

class Post < ActiveRecord::Base before_save do posttools.each { |pt| pt.mark_for_destruction if pt.tool_id.nil? } end

コンソールでは削除してないよに見えても、テーブルにはちゃんと入っていません。

投稿2019/02/08 13:39

nobinobinontan

総合スコア18

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問