On Sep 7, 2007, at 4:59 PM, Toby O'Rourke wrote:

> Hi,
>
> First post, sorry if this is the wrong place or has been answered  
> before.
>
> I'm using ActiveRecord and I want to enforce mutual exclusivity on  
> a has_and_belongs_to_many.
>
> A concrete example: I have a User which can have one or more Roles  
> (student, tutor, headmaster, administrator etc). However if a user  
> is a student they cannot hold any other role. I was hoping to find  
> something like validate_exclusive but that doesn't appear to exist.  
> Can anyone suggest how I can implement this. Otherwise, is there  a  
> better pattern I could use to model this?
>
> Many thanks,
>
> Toby.
>
>
>
It's a design pattern that occurs frequently with CRUD applications,  
in Rails or anywhere else.
I think of this pattern as the "category" pattern.
Basically you want an 'option list' (in xhtml ) and to generate that  
in Ruby/Rails you have tons of options.
Creating an option list /drop down list is covered well in AWDWR.

One way is to hard code it:
You can define a constant array or hash in your model file to provide  
a list from.
(not all models have to be in the database)

Another way is to store it (more flexible, search and sort  
capabilities are closer to ready to go):
You could also simply create a model and subsequent migration and db  
table that contains the categories for this.

Then have your User model belongs_to category (singular!) and Users  
have a category_id, integer column in the db table.

Since you're using a drop down list in the interface, there will only  
be one choice.
You could even make it more complicated with authentication  
preventing certain users from being in certain categories, but at  
that point things get messy and you might want to carefully review  
the design.


If you want to just do it with validation, you can write your own  
validates_as
In it, you just need a list of validations (think about  
capitalization, since it does matter) and you can use exclusive  
(a.k.a. XOR) or logic to match them. You could also try a case  
statement, but validations might barf on that.
If you use the exclusive or approach, you'll need to repeat the list  
of valid options in the error message of your validates_as_something

This is more of a Rails question, because it focuses on Rails models.  
But in them, you can use a lot of Ruby.
You should get AWDWR or Ruby for Rails or Rails Cookbook.

The solutions can be more or less Rubyish, but all revolve around Rails.
You could try the Rails Talk list, but you might not get as good of  
an answer there for this question as you might find in a good book.