Rails: How to get objects with at least one child?

后端 未结 6 1109
星月不相逢
星月不相逢 2021-01-03 21:10

After googling, browsing SO and reading, there doesn\'t seem to be a Rails-style way to efficiently get only those Parent objects which have at leas

6条回答
  •  抹茶落季
    2021-01-03 21:35

    try including the children with #includes()

    Parent.includes(:children).all.reject { |parent| parent.children.empty? }
    

    This will make 2 queries:

    SELECT * FROM parents;
    SELECT * FROM children WHERE parent_id IN (5, 6, 8, ...);
    

    [UPDATE]

    The above solution is usefull when you need to have the Child objects loaded. But children.empty? can also use a counter cache1,2 to determine the amount of children.

    For this to work you need to add a new column to the parents table:

    # a new migration
    def up
      change_table :parents do |t|
        t.integer :children_count, :default => 0
      end
    
      Parent.reset_column_information
      Parent.all.each do |p|
        Parent.update_counters p.id, :children_count => p.children.length
      end
    end
    
    def down
      change_table :parents do |t|
        t.remove :children_count
      end
    end
    

    Now change your Child model:

    class Child
      belongs_to :parent, :counter_cache => true
    end
    

    At this point you can use size and empty? without touching the children table:

    Parent.all.reject { |parent| parent.children.empty? }
    

    Note that length doesn't use the counter cache whereas size and empty? do.

提交回复
热议问题