search
LoginSignup
29

More than 3 years have passed since last update.

posted at

updated at

Organization

配列をActiveRecord::Relationで再取得するメソッドを作ってみる

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でエラーが出たりして頭を抱えた。

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

(コード部分だけ抜粋)

# 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)

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
29