listmania - anaylsing multiple lists in a method

Hoping someone might be able to throw me a few clues on this one.

I'm working with lists of names a User (current_user) manages lists of
names, some male some female (scoped on m or f in gender), it's all set
up such that I can do things like this - all working out fine.

(returns a list of the current users male names, pretty standard stuff I

a Name has the following attributes


What I'd like to do next is a little scary for me but I'm sure possible,
it is list comparison.

Basically for any given name, I'd like a method that returns other names
from *other users lists* where they have that given name in the list
(phew what a mouthful, not sure if that's explained correctly, I think

For example, I'd like to do this.

given user Bob has a list of male names like this


and user Sally has a list of male names like this


name = User.find_by_username('Bob').names.first
=> 'robert'

what I'd like is a method like this


which would return nil as no other users have 'robert'


name = User.find_by_username('Bob').names.last
=> 'harry'

This should return keith and paul from Sally's list.

sorry for the verbose message.

Confused if I should start with a class or instance method for starters!

Actually - thinking it through this is an instance method I believe,
acts on an instance of a name. Kind of talking out loud here.

You have not told us what is the association between user and name, is
it has_many belongs_to or has_and_belongs_to_many? The difference is
crucial because if it is has_and_belongs_to_many then if you have a
name then name.users will give you all the users that have that name,
which is half way to what you want I think.


Actually, I'll try for the instance method for the male version in

def find_similar_male
  # get all users
  users = User.all
  # get all male names
  names = Name.male
  # get the similar names
  similar_names = []

  # loop users...
  users.each do |user|
    # loop names
    user.names.male.each do |name|
      if self.given == name.given
        # match add all the names from this list into the net
        similar_names << name.given
        # or perhaps put the whole object in like similar_names << name
        # no match, do nada
      # go to next name in users list
  # go to next user in users list

Am I on the right lines at least?

Hi Colin,

Sorry - just seen your question as I was writing my method above...

User has_many names
Name belongs_to User

Is my proposed method (while probably not the most elegant) a reasonable
way of attacking the problem?

So the two 'harry's in your list are two different objects? Is that a
necessary part of your model?


Dave Aronson wrote in post #1040718:

How do I setup the habtm relationships I need an additional table right?

I'm doing it wrong aren't I ! ?

Not necessarily. If it's OK for your purposes, that two people named
Harry have their names being two different objects, your model (as I
understand it, which may be incorrectly) is perfectly fine.

I need to do habtm - find it scary tbh, never used it in anger.

Don't worry about habtm. Taken from your followup message:

How do I setup the habtm relationships I need an additional table right?

Under the hood, yes, but it happens automagically so you don't need to
be concerned with that.


You may want to consider hmt (has_many :through) instead. I've heard
habtm disparaged many times by people who couldn't get it to work, so
maybe the magic there is a bit unreliable. (Never had a problem with
it myself, though. Maybe there's a Heisenbug?)

The other, more "real", problem with habtm is that it's apparently
very difficult to retrofit into hmt, if you ever discover a need to
keep any info about the relationship. (Again, haven't run into that
problem myself, but due to lack of need, rather than having success.)
So, I tend to go with hmt to start with, even if it's only storing the
same stuff as habtm would (just the ids of the related objects).

Now, in hmt, you do need an additional table and model. In your
setup, IF you wanted to have all people named Harry point at the same
"Harry" name object, maybe I'd call it something like "namings".
Initially this would contain just the ids of the person object and the
name object. If you like, you can later use that same table to record
when the person was named, whether it's their first or middle name or
what, their preferred diminutive (perhaps as another name id), who
suggested naming the person that (as another person id), etc. etc.
etc. Adding on more data like that will be much easier with hmt than