Rails has_many链

时间:2014-10-16 18:18:01

标签: ruby-on-rails ruby has-many-through

所以我在下面有一个表结构:

平面

  • plane_id
  • plane_info

座椅

  • seating_id
  • seating_info

PlaneSeating

  • plane_seating_id
  • plane_id
  • seating_id

PlaneSeatingNote

  • plane_seating_note_id
  • plane_seating_id
  • note_id

注意

  • note_id
  • note_info

这给了我一个第三普通数据库,但我需要设置模型关系。

我目前有:

class Plane < ActiveRecord::Base

  has_many :plane_seatings, dependent: :destroy
  has_many :seatings, through: :plane_seatings

end

class Seatings < ActiveRecord::Base

  has_many :plane_seatings, dependent: :destroy
  has_many :planes, through: :plane_seatings

end

class PlaneSeating < ActiveRecord::Base

  belongs_to :plane
  belongs_to :seating
  has_many :plane_seating_notes, dependent: :destroy
  has_many :notes, through: :plane_seating_notes

end

class PlaneSeatingNote < ActiveRecord::Base

  belongs_to :plane_seating
  has_one :note

end

class Note < ActiveRecord::Base
end

现在,这将使我能够说Plane.all.first.plan_seatings.first.notes并获得我相信的笔记。但是,我希望能够说Plane.all.first.seatings.notes并获得与该飞机相关的音符。

我的想法是应该有一种方式来说,在平面:

has_many :seatings, through: plane_seating, has_many :notes, through: plane_seating

或其他一些链式魔法,以获得仅适用于该飞机和座位组合的一些音符。 a:如果你愿意的话。但是,我无法想到任何会给我这种语法的语法。有人知道吗?

2 个答案:

答案 0 :(得分:2)

最好是以另一种方式转动它,你想抓住某个平面的音符:

Note.joins(plane_seating_note: [:plane_seating]).where(plane_seating_note: {plane_seating: {plane_id: 1})

如果你在多个地方使用它并且你想在平面模型上使用它,你可以将它作为范围:

class Plane < ActiveRecord::Base

  has_many :plane_seatings, dependent: :destroy
  has_many :seatings, through: :plane_seatings

  def notes
    @notes ||= Note.for_plane_id id
  end

end

class Note < ActiveRecord::Base

  has_many :plane_seating_notes

  scope :for_plane_id ->(plane_id) { joins(plane_seating_notes: [:plane_seating]).where(plane_seating_notes: {plane_seating: {plane_id: plane_id}) }

end

对于特定飞机上的特定座位,您通常会在控制器中看到类似的内容:

@seat  = PlaneSeat.find params[:id]
@plane = @seat.plane
@notes = Note.joins(:plane_seating_notes).where(plane_seating_notes: {plane_seating_id: @seat.id})

但是既然你有HMT就可以做到

@seat  = PlaneSeat.find params[:id]
@plane = @seat.plane
@notes = @seat.notes

一对夫妇&#34; Rails-way&#34;注意到:

  1. 除非您在其他地方使用Note,否则您应该跳过plane_seat_notes。
  2. 如果您没有在中间表中附加任何额外的元数据,请考虑使用has_and_belongs_to_many;这使关系更容易,并为您提供更浅层的查询助手
  3. 考虑使用多态关系而不是不必要的连接表

答案 1 :(得分:0)

我在Plane模型中使用了一个辅助方法来获得我想要的东西。如果处理大型数据集,此方法可能效率低下,但对于我的数据集,它可以正常工作。它将每个平面的每个座位子集打包,并将与其关联的注释放入哈希值。

  #Get an easy to read hash of the seatings with their notes
  def seatings_with_notes
    @seatings_with_notes = []
    self.plane_seatings.each do |item|
      seating = Seating.where(id: item.product_application_id).first
      notes = item.notes
      combo = {seating:seating, notes:notes}
      @seatings_with_notes.append(combo)
    end
    return @seatings_with_notes
  end