I want to convert an array to Active Record Relation with Rails

Can it be converted

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.

About arrays and Active Record Relation

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.

For example, I am in trouble at such times

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 with select. I want to sort before displaying in View, so when I use the order 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.

Conclusion

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)

Implementation method

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 **

1. Create a reacquisition method in the controller or model

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.

2. Extend the Array class to create a reacquisition method

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.

Articles that I used as a reference

https://qiita.com/shibadai/items/ddbc76a8b980cd8354bc https://stackoverflow.com/questions/17331862/converting-an-array-of-objects-to-activerecordrelation

Recommended Posts

I want to convert an array to Active Record Relation with Rails
Rails6 I want to make an array of values with a check box
I want to push an app made with Rails 6 to GitHub
[Ruby] I want to put an array in a variable. I want to convert to an array
I want to play with Firestore from Rails
[Rails] I want to load CSS with webpacker
I want to ForEach an array with a Lambda expression in Java
I want to convert characters ...
I want to authenticate users to Rails with Devise + OmniAuth
[Java] I want to convert a byte array to a hexadecimal number
I want to manually send an authorization email with Devise
I want to convert InputStream to String
After posting an article with Rails Simple Calendar, I want to reflect it in the calendar.
I want to add a browsing function with ruby on rails
[Rails] I want to add data to Params when transitioning with link_to
I want to make an ios.android app
I want to use DBViewer with Eclipse 2018-12! !!
Convert an array of strings to numbers
How to convert an array of Strings to an array of objects with the Stream API
I want to introduce the committee with Rails without getting too dirty
I want to test Action Cable with RSpec test
Downgrade an existing app created with rails 5.2.4 to 5.1.6
I want to send an email in Java.
Convert a string to a character-by-character array with swift
I want to use java8 forEach with index
[Rails] How to build an environment with Docker
I want to perform aggregation processing with spring-batch
I want to be able to read a file using refile with administrate [rails6]
[Rails] I want to test with RSpec. We support your step [Introduction procedure]
[Ruby] I want to make an array from a character string with the split method. And vice versa.
How to push an app developed with Rails to Github
How can I efficiently fill an array with values?
How to make an almost static page with rails
I learned stream (I want to convert List to Map <Integer, List>)
I want to use a little icon in Rails
I want to dark mode with the SWT app
I want to monitor a specific file with WatchService
How to output standard from an array with forEach
I want to define a function in Rails Console
Rails6 I tried to introduce Docker to an existing application
I want to transition screens with kotlin and java!
How to query Array in jsonb with Rails + postgres
I want to return an object in CSV format with multi-line header & filter in Java
I want to hit the API with Rails on multiple docker-composes set up locally
I want to get along with Map [Java beginner]
I want to redirect sound from Ubuntu with xrdp
[Ruby on Rails] I want to get the URL of the image saved in Active Storage
I want to write a loop that references an index with Java 8's Stream API
[Rails] [bootstrap] I want to change the font size responsively
[Rails] I tried to create a mini app with FullCalendar
I want to build Java Applet without using an IDE
What to do when you launch an application with rails
I was addicted to setting default_url_options with Rails devise introduction
[Rails] Create API to download files with Active Storage [S3]
I want to make a list with kotlin and java!
I want to make a function with kotlin and java!
I want to create a form to select the [Rails] category
How to specify db when creating an app with rails
[Rails] I want to display "XX minutes ago" using created_at!
[Rails] I tried to implement batch processing with Rake task
Even in Java, I want to output true with a == 1 && a == 2 && a == 3