Notice that the solution you found works in one direction only:
>> Site.last.friends
[]
>> Site.last.friends << Site.first
[#<Site id: 1, name: "First", description: "The First", created_at: "2009-09-08 21:15:09", updated_at: "2009-09-08 21:15:09">]
>> Site.last.friends
[#<Site id: 1, name: "First", description: "The First", created_at: "2009-09-08 21:15:09", updated_at: "2009-09-08 21:15:09">]
>> Site.first.friends
[]
If you want it to work two ways, you can use something like:
class Site < ActiveRecord::Base
has_and_belongs_to_many :l_adjacent_sites, :class_name => 'Site', :join_table => 'sites_sites', :foreign_key => 'l_site_id', :association_foreign_key => 'r_site_id'
has_and_belongs_to_many :r_adjacent_sites, :class_name => 'Site', :join_table => 'sites_sites', :foreign_key => 'r_site_id', :association_foreign_key => 'l_site_id'
end
But the arcs are directed:
>> Site.first.r_adjacent_sites
[]
>> Site.last.r_adjacent_sites < Site.first
[#<Site id: 1, name: "First", description: "The First", created_at: "2009-09-08 21:15:09", updated_at: "2009-09-08 21:15:09">]
>> Site.last.r_adjacent_sites
[#<Site id: 1, name: "First", description: "The First", created_at: "2009-09-08 21:15:09", updated_at: "2009-09-08 21:15:09">]
>> Site.first.l_adjacent_sites
[#<Site id: 4, name: "Fourth", description: "The fourth", created_at: "2009-09-08 21:48:04", updated_at: "2009-09-08 21:48:04">]
If what you want to represent is directed arcs, you'll be fine; I haven't figured yet a solution for nondirected arcs (apart from mysite.l_adjacent_sites + mysyte.r_adjacent_sites]
).
EDIT
I tried to hack something to obtain a adjacent_sites
named_scope
or the like, but couldn't find anything; also, I'm not sure that a general solution (allowing you to filter results adding more conditions) actually exists.
Since doing l_adjacent_sites + r_adjacent_sites
forces the (two) queries execution,
I can only suggest something like:
def adjacent_sites options={}
l_adjacent_sites.all(options) + r_adjacent_sites.all(options)
end
This should allow you to do things like:
@mysite.adjacent_sites :conditions => ["name LIKE ?", "f%"]
There are still issues, though:
Sorting will not work, that is, you'll get a halfsorted set, like [1, 3, 5, 2, 4, 6]
. If you need to sort results; you'll have to do it in ruby.
Limit will only half-work: :limit => 1
will give you up to 2 results, as two queries will be executed.
But I'm positive that for most purposes you'll be ok.