Rails LEFT JOIN搜索和json

时间:2017-04-06 13:50:13

标签: mysql ruby-on-rails activerecord ruby-on-rails-5

我有以下型号:

class Address < ActiveRecord::Base
  has_many :service_records
  attr_accessor :service_record
end

class ServiceRecord < ActiveRecord::Base
  belongs_to :address
  belongs_to :plant
end

class Plant < ActiveRecord::Base
  has_one :service_record
end

我想执行一个查询,该查询将每个服务记录连接到地址和服务记录上的每个工厂。因此,例如,如果我有一个包含3个服务记录的地址,我希望获得3个结果,重复每个服务记录的地址字段,同时还包含每个服务记录的工厂信息。

到目前为止,我的查询看起来像是这样(使用Rails 5):

Address.left_joins(service_records: :plant)

返回正确数量的重复地址结果(即上面例子中的3个)。

我正在努力弄清楚的下一步是将结果查询作为包含每个地址和每个唯一服务记录的JSON结构返回。所以像这样:

[
  {
    id: 1,
    address: "1234 Street Rd",
    service_record: {
      id: 1
      plant: {
        id: 1
      }
    }
  },
  {
    id: 1,
    address: "1234 Street Rd",
    service_record: {
      id: 2
      plant: {
        id: 2
      }
    }
  },
  {
    id: 1,
    address: "1234 Street Rd",
    service_record: {
      id: 3
      plant: {
        id: 3
      }
    }
  }
]

如果您注意到,我的地址模型上有attr_accessor :service_record,但我不确定这是否是获得我需要的正确方法。任何帮助或替代方法来获得我正在寻找的东西将不胜感激!

1 个答案:

答案 0 :(得分:0)

从您的查询中,您可以使用Rails as_json和选项来实现您想要的效果。你可以这样做:

addresses = Address.left_joins(service_records: :plant)
addresses.as_json
# => [
  {
    id: 1,
    address: "1234 Street Rd"
  },
  {
    id: 1,
    address: "1234 Street Rd"
  },
  {
    id: 1,
    address: "1234 Street Rd"
  }
]

下一步是包含关联

addresses.as_json(include: :service_record)
[
  {
    id: 1,
    address: "1234 Street Rd",
    service_record: {
      id: 1
    }
  },
  {
    id: 1,
    address: "1234 Street Rd",
    service_record: {
      id: 2
    }
  },
  {
    id: 1,
    address: "1234 Street Rd",
    service_record: {
      id: 3
    }
  }
]

最后:

addresses.as_json(include: { service_record: { include: :plant } })
# => [
  {
    id: 1,
    address: "1234 Street Rd",
    service_record: {
      id: 1
      plant: {
        id: 1
      }
    }
  },
  {
    id: 1,
    address: "1234 Street Rd",
    service_record: {
      id: 2
      plant: {
        id: 2
      }
    }
  },
  {
    id: 1,
    address: "1234 Street Rd",
    service_record: {
      id: 3
      plant: {
        id: 3
      }
    }
  }
]

然后您可以微调结果。有关详情,请参阅documentation

<强>更新

如果您确定service_records数组中只有一条记录,则可以执行以下操作:

def service_record
  service_records.first
end

然后这样做

addresses.as_json(methods: :service_record)
[
  {
    id: 1,
    address: "1234 Street Rd",
    service_record: {
      id: 1
    }
  },
  {
    id: 1,
    address: "1234 Street Rd",
    service_record: {
      id: 2
    }
  },
  {
    id: 1,
    address: "1234 Street Rd",
    service_record: {
      id: 3
    }
  }
]