1. shibadai

    No comment

    shibadai
Changes in body
Source | HTML | Preview

Rubyなどで使えるmap、reject、selectなどのメソッドはとても便利だがRailsのUser.allなんかで取得したデータにこれを使うとActiveRecord::RelationクラスがただのArrayクラスになってしまい困った事態に陥りやすい。

(下記例)

[1] pry(main)> User.all
  User Load (0.9ms)  SELECT "users".* FROM "users"
=> [#<User:0x007fdf164cea08
  id: 1,
  name: "xxxxxxxxxxxxx92",
  image: "http://pbs.twimg.com/profile_images/830018730490896385/BDAl65j1_normal.jpg",
  uid: "829207717483012099",
  string: "",
  provider: "twitter",
  created_at: Tue, 05 Jun 2018 20:14:45 JST +09:00,
  updated_at: Tue, 05 Jun 2018 20:14:45 JST +09:00,
  upload_image: nil>,
 #<User:0x007fdf164c4058
  id: 2,
  name: "xxxxxxxxxxxxx",
  image: "https://avatars3.githubusercontent.com/u/25131575?v=4",
  uid: "25131575",
  string: "",
  provider: "github",
  created_at: Tue, 05 Jun 2018 20:14:54 JST +09:00,
  updated_at: Tue, 05 Jun 2018 20:14:54 JST +09:00,
  upload_image: nil>]

[2] pry(main)> User.all.class
=> User::ActiveRecord_Relation
[3] pry(main)> User.all.map{|user| user }
  User Load (1.7ms)  SELECT "users".* FROM "users"
=> [#<User:0x007fdf16456cb0
  id: 1,
  name: "xxxxxxxxxxxxx92",
  image: "http://pbs.twimg.com/profile_images/830018730490896385/BDAl65j1_normal.jpg",
  uid: "829207717483012099",
  string: "",
  provider: "twitter",
  created_at: Tue, 05 Jun 2018 20:14:45 JST +09:00,
  updated_at: Tue, 05 Jun 2018 20:14:45 JST +09:00,
  upload_image: nil>,
 #<User:0x007fdf16456b70
  id: 2,
  name: "xxxxxxxxxxxxx",
  image: "https://avatars3.githubusercontent.com/u/25131575?v=4",
  uid: "25131575",
  string: "",
  provider: "github",
  created_at: Tue, 05 Jun 2018 20:14:54 JST +09:00,
  updated_at: Tue, 05 Jun 2018 20:14:54 JST +09:00,
  upload_image: nil>]

[4] pry(main)> User.all.map{|user| user }.class
  User Load (0.5ms)  SELECT "users".* FROM "users"
=> Array

このように、User.all.classUser::ActiveRecord_Relationだったのが、mapなどを経由すると単なるArrayになってしまう。
こうなると、ActiveRecord_Relationのメソッドがうまく使えなくなったり、自分の場合はRansackの検索機能がきかなくなって頭を抱えた。

そんな時に、下記の記事が非常に助けになった。

https://qiita.com/wada811/items/12c74ed62c943c8c3f77

(コードだけ一部抜粋)

# items = [#<Item>, #<Item>, #<Item>]
@items = Item.where(id: items.map{ |item| item.id })

上記のようにすれば配列からActiveRecord::Relationにクラスを戻すことができる。
なるほど!頭いい!!と思って、自分もありがたくこの解法を使わせてもらった。

しかし、maprejectを使うたびにこのメソッドを記述するのは面倒臭い。

というわけで、下記のようなクラス復元メソッドを定義してみた。

def revive_active_record(arr)
  arr.first.class.where(id: arr.map(&:id))
end

さっそく試してみる(試しかたは適当です。。。( 'ω' ))

pp "=================================================="
pp arr=User.all.map{ |user| user }
pp "=================================================="
pp arr.class
pp "=================================================="
pp revive_active_record(arr)
pp "=================================================="
pp revive_active_record(arr).class
pp "=================================================="
"=================================================="
  User Load (0.3ms)  SELECT "users".* FROM "users"
[#<User:0x007fc335f73b68
  id: 1,
  name: "xxxxxxxxxxxxx92",
  image:
   "http://pbs.twimg.com/profile_images/830018730490896385/BDAl65j1_normal.jpg",
  uid: "829207717483012099",
  string: "",
  provider: "twitter",
  created_at: Tue, 05 Jun 2018 20:14:45 JST +09:00,
  updated_at: Tue, 05 Jun 2018 20:14:45 JST +09:00,
  upload_image: nil>,
 #<User:0x007fc335f734b0
  id: 2,
  name: "xxxxxxxxxxxxx",
  image: "https://avatars3.githubusercontent.com/u/25131575?v=4",
  uid: "25131575",
  string: "",
  provider: "github",
  created_at: Tue, 05 Jun 2018 20:14:54 JST +09:00,
  updated_at: Tue, 05 Jun 2018 20:14:54 JST +09:00,
  upload_image: nil>]
"=================================================="
Array
"=================================================="
  User Load (4.1ms)  SELECT "users".* FROM "users" WHERE "users"."id" IN (1, 2)
[#<User:0x007fc335e79000
  id: 1,
  name: "xxxxxxxxxxxxx92",
  image:
   "http://pbs.twimg.com/profile_images/830018730490896385/BDAl65j1_normal.jpg",
  uid: "829207717483012099",
  string: "",
  provider: "twitter",
  created_at: Tue, 05 Jun 2018 20:14:45 JST +09:00,
  updated_at: Tue, 05 Jun 2018 20:14:45 JST +09:00,
  upload_image: nil>,
 #<User:0x007fc335e78448
  id: 2,
  name: "xxxxxxxxxxxxx",
  image: "https://avatars3.githubusercontent.com/u/25131575?v=4",
  uid: "25131575",
  string: "",
  provider: "github",
  created_at: Tue, 05 Jun 2018 20:14:54 JST +09:00,
  updated_at: Tue, 05 Jun 2018 20:14:54 JST +09:00,
  upload_image: nil>]
"=================================================="
User::ActiveRecord_Relation
"=================================================="

特に問題なさそう。
(その役割なら、すでにあるこのメソッドでできるよとかあったら、ご教授いただけると嬉しいですm(__)m)