【问题标题】:Rails - Manipulating the returned objects in an ActiveRecord queryRails - 在 ActiveRecord 查询中操作返回的对象
【发布时间】:2017-05-14 18:34:28
【问题描述】:

所以我有以下简化的模型和关联:

class Barber < User
    has_many :barber_styles, inverse_of: :barber
end

class Style < ActiveRecord::Base
end

class BarberStyle < ActiveRecord::Base
    belongs_to :barber, inverse_of: :barber_styles
    belongs_to :style
    delegate :name, to: :style
end

如果我想根据属于特定Barber 的所有BarberStyle 进行查询,有没有办法可以包含关联Style 的名称?

我想使用类似这样的行:

BarberStyle.joins(:barber).where(barber: 109).include(:style)

这样我就可以访问关联的style.name。但我不认为这样的线路存在。

我知道我可以只使用map 来构建我自己的对象数组,但是我必须对许多不同的模型使用类似的查询,如果没有必要,我不想做很多额外的工作.

在我之前的一个项目中,我能够使用以下几行来渲染 json:

@colleges = College.includes(:sports).where(sports: { gender: "male" })
render json: @colleges, include: :sports

但我不想在这种情况下渲染 json。

编辑:

我确实没有任何未包含的关联要显示,但我会尝试进一步详细说明。

我要做的就是将额外的关联模型/字段聚合到我的 ActiveRecord 关系查询中的每个 BarberStyle 结果。

为了减少混淆,这里是我想要传递到我的 JS 视图中的数据类型的示例:

[
  #<BarberStyle 
    id: 1, 
    barber_id: 116, 
    style_id: 91,
    style: { name: "Cool Hairstyle" }
    >, 
  #<BarberStyle 
    id: 2, 
    barber_id: 97, 
    style_id: 92,
    style: { name: "Cooler Hairstyle" }
    >,
  etc...
]

我希望以这种方式格式化数据的原因是因为我无法在我的 JS 视图中对关联模型进行任何查询(没有对服务器的 AJAX 调用)。

当我过去render json: @colleges, include: :sports 时,我的数据格式非常相似。这给了我一个 Colleges 的集合,其中关联的 Sport 模型聚合到每个 College 结果。对于我目前的情况,我不想以这种方式构建 json,因为它会使一些事情复杂化。但我想这是最后的手段。

我不确定是否有一种方法可以构建 ActiveRecord 查询,它会在结果中添加额外的字段,但我觉得应该这样做,所以我正在寻找它。没有在文档中找到任何内容,但话又说回来了。

【问题讨论】:

  • 您是否尝试过设置has_many through relation?它似乎非常适合您的情况...
  • 我确实为我的Barber 模型设置了一个has_many :styles, through: :barber_styles 关联。但我排除了这一点,因为我认为这无关紧要。我正在尝试查询 BarberStyles 并将关联的样式或关联样式的名称包含在集合返回的 BarberStyle 对象中。
  • 好吧,那么请把关于你的关系的所有信息添加到你的问题中,这非常相关
  • @Doug 您能否更新您的问题并分享您的代码库中出现的 AR 之间的关联?

标签: ruby-on-rails activerecord associations


【解决方案1】:

Doug 据我了解您的代码,BarberStyle 必须是 BarberStyle 之间的连接模型。您在评论中提到您从Barber 模型中删除了has_many :styles, through: :barber_styles,因为您认为它不相关。这不是真的,这正是帮助你实现目标的关键。再次添加此关系,然后您可以执行以下操作:

barber = Barber.includes(:styles).where(barber: {id: 109})
barber.styles.each { |style| puts style.name }

由于barber.styles 是一个集合,我在所有可能的样式之间添加了一个循环。但是,由此,您可以随意使用您的数据,循环使用它或任何其他您想要的方式。

希望有所帮助!

【讨论】:

  • 感谢您的回答。但是,也许我并不清楚。我正在尝试将样式数据包含在 BarberStyles 集合中,而不必单独查询样式的名称。我将把这个集合传递给 JavaScript,它无法访问服务器。我的代码中仍然有has_many through 关联,但我只是没有在此处包含它。我想我可以自己渲染 json 并构建对象,但我的问题是是否有办法让查询集合中返回的 BarberStyle 对象中包含的那些 Style 字段
  • 你不能给你的Style 模型添加一个has_many :baber_styles 吗?如果您想获得Style````data from your BarberStyle``` 模型,我认为这是要走的路。
  • 不,我在控制器中进行查询,然后将结果呈现给 JavaScript 视图。然后在我的 JavaScript 视图中,我想遍历 BarberStyle 对象,然后获取它们所属样式的名称。除非我进行 AJAX 调用,否则我无法从我的 JS 视图访问服务器。这是使用 Rails 获取关联模型的唯一方法 - 通过查询数据库。我需要在集合中的对象中包含样式字段,以便能够从我的 JavaScript 视图中获取该信息。
【解决方案2】:

首先,在您的情况下,inverse_of 没有完成任何操作,因为您正在设置默认值。删除它。

其次,您似乎需要更好地理解 HABTM 关系的概念。 使用has many through 通常是一个好主意,因为您可以在中间的模型中添加数据和逻辑。

它非常适合你的情况,所以你应该这样设置:

class Barber < User
  has_many :barber_styles
  has_many :styles, through: :barber_styles
end

class Style < ActiveRecord::Base
  has_many :barber_styles
  has_many :barbers, through: :barber_styles
end

class BarberStyle < ActiveRecord::Base
  belongs_to :barber
  belongs_to :style
end

现在,获取给定理发师的风格是一项简单的任务。只需这样做:

barber = Barber.find(1)
barber.styles
# => AR::Collection[<#Style name:'Cool Hairstyle'>,<#Style name:'Cooler Hairstyle'>]

Rails 自动使用介于两者之间的 BarberStyle 模型来查找特定理发师的风格。 我认为这可以满足您的需求,如果您在 BarberStyle 中存储了额外信息,请告诉我。

【讨论】:

  • 作为额外说明,当您只想查询BarberStyle 时不会添加任何内容。直接去Style
猜你喜欢
  • 2021-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-15
  • 1970-01-01
  • 2018-07-06
相关资源
最近更新 更多