The SitePoint Forums have moved.

You can now find them here.
This forum is now closed to new posts, but you can browse existing content.
You can find out more information about the move and how to open a new account (if necessary) here.
If you get stuck you can get support by emailing forums@sitepoint.com

If this is your first visit, be sure to
check out the FAQ by clicking the
link above. You may have to register
before you can post: click the register link above to proceed. To start viewing messages,
select the forum that you want to visit from the selection below.

Creating a list based on a foreign relation

I've been looking around for an answer to this, and though i've found one it seems like I'm repeating myself. Here's the problem: I'm making a simple user registration page, and one of the options on it is gender (male/female/no comment) which is stored in another table, basic foreign key and such. I'd like to display this as 3 radio buttons. Is there a way to access what's in the Gender table from User model in this case? I suppose i could make a new self.genders fxn in the User model that gets everything in the foreign table but I wasn't sure if it could be handled already in rails. Any suggestions on this kind of thing?

Is there a reason why you need a table for genders anyway? Its can only ever be male/female/unknown so it only really requires a column in your user table. I can't see any benefits to having it as anything else.

Maybe I'm not understanding your question, but couldn't you just do this in the controller:

@genders = Gender.find_all

-Steven

True, this is what the self.genders definition would return in the user object. A user will have about 10 such foreign keys, so rather than creating those 10 instance variables everytime i'm displaying it, i'd want it in the user model. I'm wondering if this is part of the User model already? Could you do something like this (with slightly different code)

Code:

@user = User.new
for gender in @user.genders
(display this gender)
end

Is there a reason why you need a table for genders anyway? Its can only ever be male/female/unknown so it only really requires a column in your user table. I can't see any benefits to having it as anything else.

That'll work for displaying the gender of an already created user, but what about listing what genders are avaiable for selection?

As for why i'm listing them this way -- it seems more defined than just a bit for male/female/null (for none). You can't list out what each of those mean as a product of the database.

If you want to call it like that, you'll need to define a method in your model like:

Code:

def genders
Gender.find_all
end

Personally, I wouldn't do it that way. I would just call @genders = Gender.find_all

Often I have a view that has checkboxes and or select menus. Selected values from these menus will end up as a values for a model's attribute(s). These menus need to be displayed when creating and editing the model. I just create a protected function in the controller that gathers the values for these lists and then call it in the edit and new methods.

That'll work for displaying the gender of an already created user, but what about listing what genders are avaiable for selection?

Why can't you just create a select box or a list of radio buttons on your form? You don't need the options to be in the database, not in this case - will you ever need more than Male/Female/Unspecified?

I honestly think you need to reconsider as Gender isn't really a business object, its nothing more than a property. Its a bit of a case of using a sledgehammer to crack a nut.

Why can't you just create a select box or a list of radio buttons on your form? You don't need the options to be in the database, not in this case - will you ever need more than Male/Female/Unspecified?

I honestly think you need to reconsider as Gender isn't really a business object, its nothing more than a property. Its a bit of a case of using a sledgehammer to crack a nut.

Thanks for the input. How would you recommend storing it if not as a relation? As a varchar with the text of the option they selected?

This might not have been the best example for me to give, as this only has 2 real options. Lets say there's a drop down box was something more complex, like religion, or ethnicity. Is it the rails way to do something like

Code:

@religions = Religion.find_all

in the controller, or would it be better to define something like

Code:

def self.religions
return Religion.find_all
end

and when I need it call it directly like

Code:

for gender in User.genders

I guess this is more a best practice question at this point, now that there's a few options on the table.

Even with something like religion, it doesn't matter how many options there are, you will usually only want to list them directly in your HTML as above. Another example is a drop down list of countries. Lets say you have an Address model with an attribute called "country". Again, there is no need for a database table of countries, you simply create the list of options directly in your view. In the case of countries, as its such a common list and its so long, Rails does the hard work for you:

Code:

<%= country_select 'address', 'country' %>

The only time you really need to store options in a database table of their own is if that list needs to be manipulated in some way by end users - for instance a backend function that allows administrators to add new options. But whenever you are dealing with a fixed set of options, there is no need for a model/database table.

Finally, to take your religion example again, and lets assume you did need a database table of religions for some reason and therefore have a Religion model, there is still no need to do this:

Code:

def self.religions
return Religion.find_all
end

If all you are doing is getting a list of religions from the database so you can display them in a select box, simply do (assuming your Religion model has a name property):

Code:

@religions = Religion.find(:all)

And then in your view:

Code:

<%= collection_select 'user', 'religion', @religions, 'name', 'id' %>

That will create a select box tied to the religion property of your user model, with the options being created by looping through @religions and calling name() for the option text and id() for the option value. Example:

The bottom line though, is always consider whether something is simply an attribute of a model or an entirely separate model in itself and does the list of possible options for that attribute need to be edited by the end user? Gender definately isn't a model as its simply a property with 3 possible values. Religion could be a model but it depends on the context. If all you are interested in is the religion name, then it need be no more than a property of your user model. If however you were storing more information on each religion (therefore it would have many attributes of its own) you might have a case for a separate model.