Resurrecting an old thread because it has a useful lesson:

Marnen Laibow-Koser wrote in post #927576:
> Fearless Fool wrote:
>> [stuff about a before_destroy method using two destroy_all calls]
>
> Great!  You can probably unify those into one query and get better
> performance at the expense of a bit of Rails magic.
>
>> [stuff about an edges method that concatenates two arrays]
>
> ...which you can now probably use a variant of in :finder_sql to restore
> your has_many :edges.  Again, you may be able to refactor it into one
> query.

So as usual, Marnen is right (if not ahead of his time).  Using the
scoping constructs in Rails 3.0, this all becomes elegant and simple:

  class Edge << ActiveRecord::Base
    belongs_to :vertex_a, :class_name => 'Vertex', :foreign_key =>
'vertex_a_id'
    belongs_to :vertex_b, :class_name => 'Vertex', :foreign_key =>
'vertex_b_id'
    scope :connected_to, lambda (vertex) {
      where("edges.vertex_a_id = ? OR edges.vertex_b_id = ?", vertex.id,
vertex.id
    }
  end

  class Vertex < ActiveRecord::Base
    # caution: we are using delete_all for efficiency
    before_destroy { |vertex| Edge.connected_to(vertex).delete_all }
  end

This generates exactly the compact SQL that you'd expect, both for
finding:

  >> Edge.connected_to(v1)
  => SELECT "edges.*" FROM "edges" WHERE (edges.vertex_a_id = 2 OR
edges.vertex_b_id = 2)

and for deleting:

  >> Edge.connected_to(v1).delete_all
  => DELETE FROM "edges" WHERE (edges.vertex_a_id = 2 OR
edges.vertex_b_id = 2)

-- 
Posted via http://www.ruby-forum.com/.

-- 
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Talk" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-talk?hl=en.

Reply via email to