在ActiveRecord集合中包含关联的模型属性

时间:2018-05-04 00:48:35

标签: ruby-on-rails database activerecord collections associations

我试图以每个博客帖子对象都包含所有关联数据的方式构建我的博客帖子列表。我需要它像这样结构化,因为我将数据交给我的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

我确定我需要使用includesjoins,然后以某种方式获取属性以将其包含在集合中,但我不确定如何。

我知道如何通过使用collectmap手动形成数据结构来实现此目的,但上次使用这些方法时,我的服务器响应速度减慢了十倍。当我上次收集收集声明时,字面意思从8s变为0.8s。

2 个答案:

答案 0 :(得分:2)

您可以通过覆盖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

然后在最后使用as_json调用 BlogPost ,同时添加includes,以便一次性从关联中获取数据,如下所示:

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

<强> NB:
如果您在关联中包含大量字段,那么最好将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)

答案 1 :(得分:0)

如果您遇到性能问题,可以使用deep_pluck。它可以在不加载大量记录的情况下获取数据。因此比使用myapp-dialog-window-modal

快几倍
as_json