Reddirt
Reddirt

Reputation: 5953

Rails Controller include record and it's children

In a Rails app, I would like to create a list view that includes a master record and it's children.

Workorder Model:

  belongs_to :parent, :class_name => "Workorder", :foreign_key => "parent_id"
  has_many :children, :class_name => "Workorder", :foreign_key => "parent_id"

This is my attempt:

  def index17
    @workorder = params[:workorder_id]
    @workorders =  Workorder.find(@workorder)
    @workorders = @workorders + Workorder.find(@workorder).children    
  end

I'm trying to make the master as the first record and then all of it's children.

Rails doesn't like the "+":

undefined method `+' for #<Workorder:0x007fefcddf85f8>

Thanks for the help!

Upvotes: 0

Views: 110

Answers (4)

Tamer Shlash
Tamer Shlash

Reputation: 9523

When giving find a single value, it returns a single record - not a collection. So @workorders = Workorder.find(@workorder) gives you a single record, which doesn't have a + method. To force find to return a collection, give it an array:

def index17
  @workorder = params[:workorder_id]
  @workorders =  Workorder.find([@workorder])
  @workorders = @workorders + @workorders.first.children    
end

This works find :)

Upvotes: 0

fnln
fnln

Reputation: 230

You can always do something like @workorders.children.unshift(@workorders) to prepend to the front of the array as well.

Upvotes: 1

Paul Richter
Paul Richter

Reputation: 11081

Something like this should work:

def index17
  @workorder_id = params[:workorder_id]
  @workorder =  Workorder.find(@workorder_id)
  @workorders = [@workorder, @workorder.children].flatten
end

This will create a flat list, with the parent first, followed by its children.

Alternatively, if you'd like to try some Rails / SQL magic, you can order by the parent_id column, like so:

@workorders = Workorder.where("parent_id = ? OR (parent_id IS NULL AND id = ?)", params[:workorder_id], params[:workorder_id]).order(:parent_id)

Consequently, the parent will be on top (because the null column is ordered first, followed by each of its children. The advantage this version has is that it is one less query on the database, and at least one less line of code; both of which are always nice.

Upvotes: 0

rafb3
rafb3

Reputation: 1702

It's not that it doesn't like it, it's that @workorders is a instance of Workorder which doesn't have that method. You can use an array and then concat the children:

@parent = Workorder.find(params[:workorder_id])
@workorders = []
@workorders << @parent
@workorders.concat @parent.children # it's now [@parent, children1, children2 ...]

Upvotes: 2

Related Questions