Избегайте дублирования запросов в ActiveRecord - Ruby on Rails - PullRequest
0 голосов
/ 02 апреля 2019

У меня есть фрагмент кода с несколькими простыми запросами, и я пытаюсь оптимизировать его, сжимая их в один запрос.Но я понятия не имею, как.

posts = Post.where(category: "article")
num_posts = posts.count
first_post = posts.first
posts_with_updated_name = posts.map { |post| post[:name] = "UPDATE_" + post[:name] }

Я хотел иметь один запрос, который будет выполнен в первой строке, а затем posts будет массивом для выполнения.операции в строках 2, 3 и 4. Вместо этого я получаю 3 отдельных запроса.Любая идея, как оптимизировать это в один запрос?

LE: Вы можете предположить, что num_posts, first_post и posts_with_updated_name - это просто переменные, которые мне понадобятся позже

Ответы [ 2 ]

2 голосов
/ 02 апреля 2019

Поскольку преобразование объекта ActiveRecord::Relation в Array может потенциально потреблять большой объем памяти (и может даже не хватить памяти) для большой базы данных, я бы сделал следующее, в котором все равно будет использоваться (2 + число-пакетов) SQL-запросов, но ваше приложение будет масштабироваться в долгосрочной перспективе.

posts = Post.where(category: "article")
num_posts = posts.count
first_post = posts.first

# || is a PostgreSQL operator for string concatenation
# if you are using MySQL check out CONCAT instead
posts_with_updated_name = posts.select('posts.*', "'UPDATE_' || name AS updated_name")

# example usage
posts_with_updated_name.find_each do |post|
  puts post.id
  puts post.name
  puts post.updated_name
end

# example output:
# 6
# 'Spider Man is Back'
# 'UPDATE_Spider Man is Back'
# 84
# 'Hello World'
# 'UPDATE_Hello World'

Рекомендуемое решение

1.Временное «Обновленное имя»

Я не буду хранить «обновленное имя» в переменной, но добавлю / добавлю строку только по требованию, как показано ниже:

posts = Post.where(category: "article")
num_posts = posts.count
first_post = posts.first

# somewhere in your code where you are actually already gonna be looping over `posts`
posts.find_each do |post|
  updated_name = "UPDATE_#{post.name}'"
  # do something here about updated name
end

2.Постоянное «Обновленное имя»

Или ... если это значение «Обновленное имя» является постоянной логикой в ​​приложении, просто напишите метод в модели:

app/models/post.rb

class Post < ApplicationRecord
  # ...

  def updated_name
    "UPDATE_#{name}"
  end
end

Тогда в вашем коде вы просто будете делать следующее без необходимости устанавливать значение для «обновленного имени»,

posts = Post.where(category: "article")
num_posts = posts.count
first_post = posts.first

# example:
puts first_post.updated_name
# => 'UPDATE_Hello World'
1 голос
/ 02 апреля 2019

Я не уверен, хорошо ли я понимаю ваш вопрос, но я думаю, что вы хотите преобразовать коллекцию ActiveRecord в массив? Если это так, вы можете сделать это с posts = Post.where(category: "article").to_a

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...