Включить атрибуты связанной модели в коллекцию ActiveRecord - PullRequest
0 голосов
/ 04 мая 2018

Я пытаюсь структурировать свой список сообщений в блоге так, чтобы каждый объект сообщения в блоге имел все связанные данные. Мне нужно, чтобы это было структурировано так, потому что я передаю данные в мой JavaScript-интерфейс.

Мне нужна структура данных с простыми записями, подобными этой:

[
<BlogPost id: 12,
  image: "image.png",
  title: "corrupti",
  content: "\n## Fuga eveniet beatae necessitatibus excepturi c...",
  blog_author: {
    id: 8,
    name: "Theodan Wells"
  },
  blog_category: {
    id: 6,
    name: "Marketing"
  }>
]

Ассоциации, вероятно, очевидны, но все равно вот мои модели:

class BlogPost < ApplicationRecord
  belongs_to :blog_author, inverse_of: :blog_posts
  belongs_to :blog_category, inverse_of: :blog_posts
end

class BlogAuthor < ApplicationRecord
  has_many :blog_posts, inverse_of: :blog_author
end

class BlogCategory < ApplicationRecord
  has_many :blog_posts, inverse_of: :blog_category
end

Я уверен, что мне нужно использовать includes или joins, а затем каким-то образом собрать атрибуты, чтобы включить их в коллекцию, но я просто не знаю, как это сделать.

Я знаю, как это сделать, вручную сформировав структуру данных с помощью collect и map, но в прошлый раз, когда я использовал эти методы, мои серверные ответы замедлились в десять раз. Буквально пошло с 8 до 0,8, когда я в прошлый раз вынул выписки.

Ответы [ 2 ]

0 голосов
/ 04 мая 2018

Вы можете использовать deep_pluck , если у вас есть проблемы с производительностью. Он может собирать данные, не загружая кучу записей. Следовательно, в несколько раз быстрее, чем as_json

BlogPost.deep_pluck(
  :id, 
  :image, 
  :title, 
  :content,
  blog_author: [:id, :name],
  blog_category: [:id, :name],
)
0 голосов
/ 04 мая 2018

Вы можете сделать это, переопределив метод as_json, как показано ниже:

class BlogPost < ApplicationRecord
  belongs_to :blog_author, inverse_of: :blog_posts
  belongs_to :blog_category, inverse_of: :blog_posts

  def as_json(options = {})
    if options[:index]
      {
          id: id,
          image: image,
          title: title,
          content: content,
          blog_author: {
                         id: blog_author.id,
                         name: blog_author.name
                       },
          blog_category: {
                         id: blog_category.id,
                         name: blog_category.name
                          }
      }
    else
      super
    end
  end

end

Затем вызовите BlogPost с as_json в конце, также добавьте includes, чтобы он получал данные из ассоциации за один раз, как показано ниже:

BlogPost.inlcudes(:blog_author,:blog_category).as_json(index: true)

Примечание:
Если в ассоциации много полей, то лучше добавить select с joins к вашему запросу, чтобы выбрать точные поля, как показано ниже:

    BlogPost.joins(:blog_author,:blog_category)
            .select("blog_posts.id,blog_posts.image,blog_posts.content ,blog_posts.title, blog_authors.id, blog_authors.name, blog_categories.id, blog_categories.name")
            .as_json(index: true)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...