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.