【Rails】ActiveRecord::Relationを配列にしたい、インスタンスをpushしたい

2018年4月22日

結論から。

(例)

@users = User.find(3,5)
user6 = User.find(6)
@users + [user6]

これで出来ました。

@users = User.where("nickname like ?", "\%鈴木\%")
user6 = User.find(6)
@users + [user6]

こういう形もできます。

テックアカデミーの講師の方に教えていただいた。。半日悩んだのに一瞬でした(; ・ω・´)

目的はアクティブレコードのインスタンスを繋げたい

アクティブレコードのインスタンスを繋げていきたいというのが目的でした。

何かと言うと自前のDBに入ってるshopsテーブルから条件検索でshopのインスタンスを取ってくる。そこに別のshopを繋げたいと思ったのです。

色々試してみたのですが、最初はpushメソッドを使っていました。

rails cでコンソールで確認していました。

この書き方はエラーが出ず、user3の後ろにuser5をつなげる事ができました。

user3 = User.find(3)
user5 = User.find(5)
users = []
users.push(user3)
users.push(user5)

結果はちゃんと配列の形になりました。

[#<User id: 3, nickname: "山さん", email: "", password_digest: "...", image: "", created_at: "2018-04-09 10:26:41", updated_at: "2018-04-18 04:57:21">,
#<User id: 5, nickname: "ののちゃん", email: "", password_digest: "...", image: "", created_at: "2018-04-09 10:38:00", updated_at: "2018-04-18 05:18:58">]

ところがこういう場合は理想の配列になりません。

user35 = User.find(3,5)
user6 = User.find(6)
users = []
users.push(user35)
users.push(user6)

結果はこのような形で配列の中に配列ができちゃいました。→ [[a,b],c]みたいな形。

[[#<User id: 3, nickname: "山さん", email: "", password_digest: "...", image: "", created_at: "2018-04-09 10:26:41", updated_at: "2018-04-18 04:57:21">,
#<User id: 5, nickname: "ののちゃん", email: "", password_digest: "...", image: "", created_at: "2018-04-09 10:38:00", updated_at: "2018-04-18 05:18:58">],
#<User id: 6, nickname: "かりんちゃん", email: "", password_digest: "...", image: "", created_at: "2018-04-13 04:44:29", updated_at: "2018-04-13 13:01:29">]

なので
user35 = User.find(3,5)の部分を配列に変換したいという風に思ったのです。いや、配列なんだけどね。

この記述はどうでしょうか。

user35 = User.find(3,5)
user6 = User.find(6)
user35.push(user6)

結果はこのような形で配列ができました。[a,b,c]みたいな形になっています。

=> [#<User id: 3, nickname: "山さん", email: "", password_digest: "...", image: "", created_at: "2018-04-09 10:26:41", updated_at: "2018-04-18 04:57:21">,
#<User id: 5, nickname: "ののちゃん", email: "ant.co.jp", password_digest: "...", image: "", created_at: "2018-04-09 10:38:00", updated_at: "2018-04-18 05:18:58">,
#<User id: 6, nickname: "かりんちゃん", email: "", password_digest: "...", image: "", created_at: "2018-04-13 04:44:29", updated_at: "2018-04-13 13:01:29">]

なるほど。配列にpushメソッドをすれば繋がるのか。

ではこの記述はどうでしょうか。

user3 = User.find(3)
user6 = User.find(6)
user3.push(user6)

結果は

NoMethodError: undefined method push’ for #<User:0x00000005aff0a0>

このようなエラーが出ました。user3は配列じゃないからそんなメソッド無いよ、と言われました。

findメソッドと、whereメソッドだったら違うのかな。
と思って調べたら全然ちがいました。

findメソッドとwhereメソッドの違い

findメソッドでIDを指定して取れる1個のインスタンスはモデルのインスタンスです。IDが無ければエラーが出ます。またIDを複数指定して取れるのはただのモデルが入った配列です。

一方、whereメソッドで取れるデータは必ず配列[]です。データが1件でも配列で返ってきます。で、これこそがアクティブレコードリレーション(ActiveRecord::Relation [])と呼ぶようです。

だからそもそもfindとwhereでは返り値の型が違っていたようです。

ここからwhereで調べました。

user37 = User.where(“nickname like ?”, “\%さん\%”)
=> #<ActiveRecord::Relation [#<User id: 3, nickname: “山さん”, email: “”, password_digest: “…”, image: “”, created_at: “2018-04-09 10:26:41”, updated_at: “2018-04-18 04:57:21”>,
#<User id: 7, nickname: “鈴木さん”, email: “”, password_digest: “suzuki”, image: nil, created_at: “2018-04-20 07:32:07”, updated_at: “2018-04-20 07:32:07”>]>

user6 = User.find(6)
user37.push(user6)
NoMethodError: undefined method `push’ for #<User::ActiveRecord_Relation:0x0000000596a028>

エラーでた。配列だからpushメソッドあると思ったのに。。

ActiveRecord::Relationにはpushというメソッドは無いようです。

配列を用意してそこに入れてみます。

user = []
user.push(user37)
=> [#<ActiveRecord::Relation [#<User id: 3, nickname: “山さん”, email: “”, password_digest: “…”, image: “”, created_at: “2018-04-09 10:26:41”, updated_at: “2018-04-18 04:57:21”>,
#<User id: 7, nickname: “鈴木さん”, email: “”, password_digest: “suzuki”, image: nil, created_at: “2018-04-20 07:32:07”, updated_at: “2018-04-20 07:32:07”>]>]

[[a,b]]こんな感じになっちゃった。

さらに追加。

user.push(user6)
=> [#<ActiveRecord::Relation [#<User id: 3, nickname: “山さん”, email: “”, password_digest: “…”, image: “”, created_at: “2018-04-09 10:26:41”, updated_at: “2018-04-18 04:57:21”>,
#<User id: 7, nickname: “鈴木さん”, email: “”, password_digest: “suzuki”, image: nil, created_at: “2018-04-20 07:32:07”, updated_at: “2018-04-20 07:32:07”>]>,
#<User id: 6, nickname: “かりんちゃん”, email: “”, password_digest: “…”, image: “”, created_at: “2018-04-13 04:44:29”, updated_at: “2018-04-13 13:01:29”>]

[[a,b],c]こんな感じになっちゃった。

うまくいかない。pushメソッドは駄目っぽい。

ActiveRecord::Relationを配列にしてインスタンスを繋げたい、結論

で、教えていただいたのがこちら。

user37 = User.where(“nickname like ?”, “\%さん\%”)
user6 = User.find(6)
user37 + [user6]
=> [#<User id: 3, nickname: “山さん”, email: “”, password_digest: “”, image: “”, created_at: “2018-04-09 10:26:41”, updated_at: “2018-04-18 04:57:21”>,
#<User id: 7, nickname: “鈴木さん”, email: “”, password_digest: “suzuki”, image: nil, created_at: “2018-04-20 07:32:07”, updated_at: “2018-04-20 07:32:07”>,
#<User id: 6, nickname: “かりんちゃん”, email: “”, password_digest: “…”, image: “”, created_at: “2018-04-13 04:44:29”, updated_at: “2018-04-13 13:01:29”>]

うーん。綺麗につながってます。

これでActiveRecord::Relationをpushが使える配列にする必要がなくなりました。

ここまで検索したキーワード
Rails インスタンスを配列に直す
Rails アクティブレコードを配列に変換
ActiveRecord::Relationを配列に変換する

途中、pluckというメソッドが使えるらしいという記事を読みはじめてドハマリしました。本来はそっちの目的で検索する人が多いんだろうなぁ。