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.class
がUser::ActiveRecord_Relation
だったのが、mapなどを経由すると単なるArray
になってしまう。
こうなると、ActiveRecord_Relationのメソッドがうまく使えなくなったり、自分の場合はRansackでエラーが出たりして頭を抱えた。
そんな時に、下記の記事が非常に助けになった。
(コード部分だけ抜粋)
# items = [#<Item>, #<Item>, #<Item>]
@items = Item.where(id: items.map{ |item| item.id })
上記のようにすれば配列からActiveRecord::Relationにクラスを戻すことができる。
なるほど!頭いい!!と思って、自分もありがたくこの解法を使わせてもらった。
しかし、map
やreject
を使うたびにこのメソッドを記述するのは面倒臭い。
というわけで、下記のようなクラス復元メソッドを定義してみた。
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)