SitePoint Sponsor

User Tag List

Results 1 to 9 of 9
  1. #1
    SitePoint Member Dyogenez's Avatar
    Join Date
    Oct 2004
    Location
    Orlando, FL
    Posts
    24
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    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?

  2. #2
    SitePoint Enthusiast Stevenwulf's Avatar
    Join Date
    May 2002
    Location
    Berkeley
    Posts
    76
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Maybe I'm not understanding your question, but couldn't you just do this in the controller:

    @genders = Gender.find_all

    -Steven

  3. #3
    SitePoint Guru silver trophy Luke Redpath's Avatar
    Join Date
    Mar 2003
    Location
    London
    Posts
    794
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You need to look into activerecord associations.

    Code:
    class User < ActiveRecord::Base
      has_one :gender
    end
    
    class Gender < ActiveRecord::Base
      belongs_to :user
    end
    
    user = User.find(1)
    puts user.gender.some_gender_property
    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.

  4. #4
    SitePoint Member Dyogenez's Avatar
    Join Date
    Oct 2004
    Location
    Orlando, FL
    Posts
    24
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Stevenwulf
    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
    Or would this require adding the 'genders' method to the user model?

  5. #5
    SitePoint Member Dyogenez's Avatar
    Join Date
    Oct 2004
    Location
    Orlando, FL
    Posts
    24
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Luke Redpath
    You need to look into activerecord associations.

    Code:
    class User < ActiveRecord::Base
      has_one :gender
    end
    
    class Gender < ActiveRecord::Base
      belongs_to :user
    end
    
    user = User.find(1)
    puts user.gender.some_gender_property
    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.

  6. #6
    SitePoint Enthusiast Stevenwulf's Avatar
    Join Date
    May 2002
    Location
    Berkeley
    Posts
    76
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    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.

  7. #7
    SitePoint Guru silver trophy Luke Redpath's Avatar
    Join Date
    Mar 2003
    Location
    London
    Posts
    794
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dyogenez
    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.

  8. #8
    SitePoint Member Dyogenez's Avatar
    Join Date
    Oct 2004
    Location
    Orlando, FL
    Posts
    24
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Luke Redpath
    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.

  9. #9
    SitePoint Guru silver trophy Luke Redpath's Avatar
    Join Date
    Mar 2003
    Location
    London
    Posts
    794
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dyogenez
    I guess this is more a best practice question at this point, now that there's a few options on the table.
    Well I'm trying to help you with best practice but you don't seem to get what I'm saying.

    How would you recommend storing it if not as a relation? As a varchar with the text of the option they selected?
    Exactly. Gender is simply an attribute of your user, not an entirely separate entity that needs modelling and its own database table.

    If all you want to do is simply present a list of options for a particular attribute of your model, say in this case the gender attribute of your user model, simply code that into your form.

    In your user form (view):

    Code:
    <%= select('user', 'gender', %w(Male Female Unspecified)] %>
    outputs:

    Code:
    <select name="user[gender]">
      <option>Male</option
      <option>Female</option
      <option>Unspecified</option
    </select>
    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:

    Code:
    <select name="user[religion]">
      <option value="1">Islam</option>
      <option value="2">Buddhism</option>
      <!-- etc -->
    </select>
    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.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •