如何在Rails中合并具有一对多关系的两个模型?

时间:2018-02-16 19:37:23

标签: ruby-on-rails ruby model rails-activerecord

我有两个模型,比如说AuthorBook,其中Author有很多Book个。我必须通过AJAX获取Author个名称及其各自Books名称的列表。

我有一些想法,但不知道哪一个是最好的。

  1. 独立获取它们(所有AuthorBook并使用过滤器在JavaScript中对它们进行分组),但似乎将服务器应该在JavaScript上完成的工作。
  2. 创建一个包含AuthorBook数组的ruby类/结构。查询Author s并为每个查询查询相应的Book,但这似乎不必要地进行了多次数据库查询。
  3. 与上面相同,但不是包装类,而是获取Author s的属性'哈希值,并插入Book s的属性哈希值。与多个查询相同的问题。
  4. 最好在一个查询中以某种方式连接表,以检索已与其Author合并的所有Book。像sql join这样的东西,但是对于一对多的关系(如果这种关系甚至存在的话)。

3 个答案:

答案 0 :(得分:1)

Active Model Serializer是一种快速简便的解决方案。它将您的数据序列化为json,并提供完全控制您要显示的属性。

在你的gemfile中:

gem 'active_model_serializers'

然后运行以下命令:

bundle install
rails g serializer Author
rails g serializer Book

现在您将生成2个新文件。

author_serializer.rb

class AuthorSerializer < ActiveModel::Serializer
  attribute :id  
  # add your other author attributes here such as:
  # attribute :name
  # attribute :age
  has_many :books
end

book_serializer.rb

class BookSerializer < ActiveModel::Serializer
  attribute :id  
  # add your other book attributes here such as:
  # attribute :title
  # attribute :publisher
end

authors_controller.rb

class AuthorsController < ApplicationController

  def index
    render status: :ok, 
           json: Author.all, 
           each_serializer: AuthorSerializer
  end

  def show
    render status: :ok, 
           json: Author.find(params[:id]), 
           serializer: AuthorSerializer
  end
end

请注意索引指定each_serializer并显示指定serializer

答案 1 :(得分:1)

你可以做到

Author.includes(:books)

这将生成两个查询,一个用于作者,一个用于书籍,您将获得一组“作者”对象,每个对象都有一系列“书籍”。

答案 2 :(得分:1)

要将AuthorBook序列化为JSON,您可以向include提供to_json参数:

class SomeJsonController < ApplicationController
  def show
    author = Author.find(params[:id])
    respond_to do |format|
      format.json { render json: author.to_json(include: :books) }
    end
  end
end

完整文档可用hereactive_model_serializer也可以工作(并且如果您需要为关联呈现JSON的这类案例,将会更好地扩展)但如果您只有一个案例可能会有点过分。