SitePoint Sponsor

User Tag List

Results 1 to 7 of 7
  1. #1
    SitePoint Enthusiast
    Join Date
    Jan 2005
    Location
    Amersfoort, the Netherlands
    Posts
    50
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Question Losing mind over has_one association, please help

    Hi everyone. I've been bending my head around a has_one association for about 3 hours now and I can't get it to work. I'm pretty sure it's not something I'm overlooking anymore. Here's the essential part of the schema I'm working with:

    Code:
    topics(id, last_post_id)
    posts(id, topic_id)
    Topics are simply named containers for posts. I decided not to use virtual tables since 99% of the columns would be topic-related. In the Topic model I have the following associations:

    Code:
    has_many(:posts)
    has_one(:last_post, {:class_name => 'Post'})
    Next, in the Post model, I have the following hook which should update the topic whenever a new post is added:

    Code:
    def after_create
      self.topic.last_post = self
    end
    Posts are added properly to the topics (@topic.posts << @post; @topic.save), yet somehow, every topic I add (1 post included) has NULL for the last_post_id. Please help, I'm losing my mind.

  2. #2
    SitePoint Guru
    Join Date
    Aug 2005
    Posts
    986
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It is weird, but I think you have to use belongs_to instead of has_one, because the foreign key should be in the table which has belongs_to.

  3. #3
    SitePoint Enthusiast
    Join Date
    Jan 2005
    Location
    Amersfoort, the Netherlands
    Posts
    50
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I think you're right. I couldn't find the issue on Google yesterday, but I read about a similar problem a couple of hours ago.

    Now, let's say a Topic has both a first_post and a last_post (both Post classes), would it be possible to have Topic.find() sort the results by first_post.created_at or last_post.created_at?

  4. #4
    SitePoint Guru
    Join Date
    Aug 2005
    Posts
    986
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I think it is...but you have to use SQL, Rails doens't provide a magical way to do this. Are you familiar with SQL, or do you need help?

  5. #5
    SitePoint Zealot
    Join Date
    Sep 2000
    Location
    England
    Posts
    120
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Not sure this is quite what you're after, but this is what I did to define first and last posts in a forum topic/thread:
    Code:
     class Topic < ActiveRecord::Base
    
      has_many :posts,
    		   :order => 'dte_created ASC'
      # Get first post (i.e. the topic starter)
      has_one :first_post,
    		  :class_name => 'Post',
    		  :order => 'parent_id ASC'
      # get last post to this thread
      has_one :last_post,
    		  :class_name => 'Post',
    		  :order => 'id DESC'
    end
    You could change the order by fields to whatever you need to get the earliest and latest posts depending on your database setup.

  6. #6
    SitePoint Enthusiast
    Join Date
    Jan 2005
    Location
    Amersfoort, the Netherlands
    Posts
    50
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    @ Fenrir2: I just realized that if I have the foreign ID's (first_post and last_post) stored in the table, I could sort by them as a newer post will always have a higher ID and vice versa Thanks anyway!

    @ adamp: I tried that, but were you able to sort the topic list by, say, topic title, last post date or first post date using that association?

  7. #7
    SitePoint Zealot
    Join Date
    Sep 2000
    Location
    England
    Posts
    120
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I just wrote a basic forum in order to first get to grips with Rails, so didn't take it very far, but if you need to sort the post list by various fields you should be able to replace the 'dte_created ASC' part of the rder call with a call to a function that checks the @params for the field and direction to sort on.

    Something like
    Code:
      has_many :posts,
     	:order => get_sort_order
     
      def get_sort_order
          order_query = @params[:orderby] + ' ' + @params[:direction]
      end
    You'd obviously want to set a default order clause in case no field/direction params are passed, but the above should show the general idea. You can then have your links for different ordering, e.g.
    Code:
    link_to 'Title', :action => 'list', :orderby => 'title', :direction => 'ASC'
    ... or whatever.


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
  •