Search code examples
ruby-on-railsruby-on-rails-3model-view-controllerroutesbelongs-to

Rails: Forum has_many topics, saving the association?


I might be going about this the wrong way in the first place, so I will give a bit of background first.

As you can tell from the title, I am building a forum from scratch. I thought it was working correctly; however, I am a bit unsure as to how to update/save the forum object from within the topics "create" method in it's controller.

What I tried to do: In the "New" method, I sent the Forum's id via the routing. So on the new-topic page has a address that looks like this: "localhost:3000/new-topic/1". The one being the Forum's id. In the method itself, I try to attach it to the new topic object.

@topic = Topic.new
@topic.forum = Forum.find(params[:id])

My create method then tries to use that forum.

@topic = Topic.new(params[:topic])
@topic.forum.topics << @topic #Simplified down.
if @topic.save
  @topic.forum.save
...

I get the feeling that I am going about this the wrong way. I was looking at someone's tutorial and they got the forum by calling params[:forum_id] but they didn't show they routing they did to achieve that.

How do I do this correctly and/or what is the correct way to route all of this? For the record, I do plan on using this same method for the Topic => Post association. Thanks for any help.


Solution

  • You should use nested REST routes:

    # routes.rb
    resources :forums do
      resources :topics
    end
    

    this will result in the following routes:

    GET  /forums/:forum_id/topics/new # displays the form
    POST /forums/:forum_id/topics     # creates the topic
    

    and in controller you should use builders, they have several advantages like security, scope preserving etc.:

    def new
      @forum = Forum.find(params[:forum_id])
      @topic = @forum.topics.build
    
    def create
      @forum = Forum.find(params[:forum_id])
      @topic = @forum.topics.build(params[:topic])
      if @topic.save
        ...
    

    http://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Resources.html#method-i-resources