I will write it first because it may be misleading. I'm sure some of you are reading this article because you want to convert an array to Active Record Relation. Strictly speaking, ** arrays cannot be converted to Active Record Relation. ** ** However, you can get Active Record Relation using the ** obtained array. ** **
I personally searched for "array Active Record Relation conversion", so I dare to give it a title like this.
I will explain briefly at the beginning, but if you understand it, please skip up to here. Let me give you an example of an array and Active Record Relation.
#Create Active Record Relation.
AdminUser.where(id: [2, 3])
=> [#<AdminUser:0x00007fd2621de8e0
id: 2,
name: "Yamada">,
#<AdminUser:0x00007fd2621de4f8
id: 3,
name: "Sato">]
#Create an Array.
AdminUser.where(id: [2, 3]).select(&:name)
=> [#<AdminUser:0x00007fd26231ad80
id: 2,
name: "Yamada">,
#<AdminUser:0x00007fd26231aa88
id: 3,
name: "Sato">]
The results look the same, but you can see the difference by adding .class
.
AdminUser.where(id: [2, 3]).class
=> AdminUser::ActiveRecord_Relation
AdminUser.where(id: [2, 3]).select(&:name).class
=> Array
When retrieving data from a model, you may use various methods such as where
, find
, select
, and map
, but in Rails, the return type is determined by the method used. I will.
In the usage of the above example, where
will return Active Record Relation, and select
will return the Array class.
select
returns Active Record Relation depending on how it is used.I want to display some data in View. It's okay to use
where
to make Active Record Relation, After that, I narrowed down the data withselect
. I want to sort before displaying in View, so when I use theorder
method, an error occurs.
A method called order
that is often used when developing with Rails. You can sort.
#Sort in descending order of id
AdminUser.where(id: [2, 3]).order(id: :desc)
=> [#<AdminUser:0x00007fd260347a30
id: 3,
name: "Sato",
#Omitted below
Using this order
method on an Array class will result in an error like this:
AdminUser.where(id: [2, 3]).select(&:name).order(id: :desc)
=> NoMethodError: undefined method `order' for #<Array:0x00007fd26027d578>
In such cases, there is a desire to convert AdminUser.where (id: [2, 3]). Select (&: name)
to Active Record Relation.
Here is a concrete way to fulfill the desire like the title. If you want to create an Active Record Relation called @admin_users from an Array class called admin_users, do this.
admin_users = AdminUser.where(id: [2, 3]).select(&:name)
@admin_users = AdminUser.where(id: admin_users.map(&:id))
In short, I'm just doing where (id: admin_users.map (&: id))
,
What I'm doing is taking out only the id of the existing array, creating an array, and using it as the argument of where
to get the data again from AdminUser.
Are there any points to note?
--The order of the data contents may change --The process of reacquiring the data is being performed (it takes extra time for a large amount of data)
When implementing using this process, if you do a lot of the same process, I would like to summarize it neatly. Here are two methods.
** 1. Create a reacquisition method on the controller or model ** ** 2. Extend the Array class to create a reacquisition method **
Write the following on the controller or model.
def self.get_activerecord_relation(arr)
where(id: arr.map(&:id))
end
How to use
admin_users = AdminUser.where(id: [2, 3]).select(&:name) => #Array class
@admin_users = AdminUser.get_activerecord_relation(admin_users) => #Active Record Relation
I think it feels a little uncomfortable.
Create a file called array.rb.
lib/core_ext/array.rb
class Array
def to_activerecord_relation
return ApplicationRecord.none if self.empty?
clazzes = self.map(&:class).uniq
raise 'Array cannot be converted to ActiveRecord::Relation since it does not have same elements' if clazzes.size > 1
clazz = clazzes.first
raise 'Element class is not ApplicationRecord and as such cannot be converted' unless clazz.ancestors.include? ApplicationRecord
clazz.where(id: self.map(&:id))
end
end
Create a file called core_ext.rb.
config/initializers/core_ext.rb
require 'core_ext/array'
How to use
admin_users = AdminUser.where(id: [2, 3]).select(&:name) => #Array class
@admin_users = admin_users.to_activerecord_relation => #Active Record Relation
Method 2 is a method that uses a function called Ruby's open class that allows you to add methods later.
It's like letting the Array class use a method called to_activerecord_relation
for the whole thing.
Regarding open classes, other than those introduced this time, for example,
You can also add a method called to_bool
to the String class so that objects with the strings"true"
and"false"
can be converted to boolean types.
https://qiita.com/shibadai/items/ddbc76a8b980cd8354bc https://stackoverflow.com/questions/17331862/converting-an-array-of-objects-to-activerecordrelation
Recommended Posts