A simple forum in rails

I've to make a simple forum for my app.
The idea was to have:
Forum -has many < Forum_subjects -has many< posts

Now I've made a form in which the user enters the subject and the
first post, it was easy to add the subject to the forum :

params[:forum_subject][:forum_if] = 1 unless params[:forum_subject]
[:forum_id]
    forum = Forum.find_by_id(params[:forum_subject][:forum_id])
    @forum_subject = ForumSubject.new(params[:forum_subject])
    if @forum_subject.save
      forum.forum_subjects << @forum_subject
        redirect_to :controller=>:forum, :action=>:list

    end
  end

I dont really know how to add a new post to this at the same time
I could assume to do that this way:
- create new forum subject
- get the last insert_id of the forum_subject
- add new post to the subject
The thing is I cant find the way to get the last insert_id (for
finding the subject)

I guess there is another way of doing this, but I lack skill in
rails...

Forum:
has_many :subjects
has_many :posts, :through => :subjects
Subject:
belongs_to :forum
has_many :posts
Posts
belongs_to :subject
Don’t call them forum_subjects as that is violating the DRY (Don’t Repeat Yourself) principle.
params[:forum_subject][:forum_id] = 1 unless params[:forum_subject][:forum_id]

Any reason for this? What if the first forum gets deleted?

forum = Forum.find_by_id(params[:forum_subject][:forum_id])

Instead of using find_by_id just use find, that is unless you want to
return nil rather than an ActiveRecord::RecordNotFound exception (which
should never occur unless the user does something wrong)

@forum_subject = ForumSubject.new(params[:forum_subject])

@subject = forum.subjects.create!(params[:subject]) change in your form, forum_subject to just subject, as I have done in the models.

add new post to the subject
@post = @subject.posts.create!(params[:post])

I also recommend using restful routing as it saves a lot of effort, for example having to put forum_id into the form for the subject.

http://frozenplague.net/2008/01/06/restful-routing-an-overview/

OK, Thank you very much.
I'll get right on it after work :slight_smile:

What's the model for your posts? Post? Do you have a controller
specific, a default one, for that controller?

-Thufir

Right now i've folowed the tutorial, i'm stuck @ adding new topic and
the first post at the same time.
I'll post the code later, tired at the time...

Adam, if you’re still looking for some help I’ll be glad to help you out, add me as radarlistener@gmail.com on MSN if you have it, or on googletalk. Alternatively you can shoot me an email.

I guess what I'm doing right now is pretty simple but after a days
work it can be hard to figure it out.

I did a pretty simple form for topic and the post, like in a usual
forum the user can create a topic and add the first post.
Here's the short version of the form.

<%form_for @topic do |f| %>
<%= f.hidden_field :user_id, :value=>session[:user_id] %>
<%= f.hidden_field :forum_id, :value=>@forum%>
<%= render :partial=>'topics/form',:locals=>{:f=>f} %>
<%fields_for @post do |p| %>
<fieldset class="alt">
  <%= p.text_field :subject,:size=>100%>
  <%= p.text_area :body %>
</fieldset>
<%end %>
<%end %>

in the address bar before sending i've got host/forums/2/topics/new.

def create
    @forum = Forum.new params[:forum_id]
    @topic = Topic.new params[:topic]
    @forum.topics << @topic

    @post = Post.new params[:post]
    @topic.save!
    @post.save!
    @topic << @post
     redirect_to forum_path(@topic.forum_id)
  rescue ActiveRecord::RecordInvalid
    render :action => :new
  end

In the above part i'm doing something wrong cause i get a error
                topic_id cannot be null ...

and when i change Post.new params[:topic][post]
i get a validation error saying that body of the post cannot be null
and a redirection to /topics

So i guess the solution is pretty simple in here , but i lack skills,
I'm working on them thought :slight_smile:

You shouldn’t need to pass in user_id and forum_id as hidden fields, as user_id should be stored as a session variable (session[:user]) and forum_id should come from the URL.

@forum = Forum.find(params[:forum_id])
@topic = @forum.topics.build(params[:topic])
@topic.posts.build(params[:post])
@forum.save!

That should do it.

I dont really know why but in the version above the forum_id isn't
passed within the url
i get a Couldn't find Forum without an ID error.

What’s the URL look like? It needs to have the forum_id in there, so like /forums/1/topics should be the URL.

Yes the url looks like that forums/1/topics/new, after sending it it
changes to /topics and then throws an error

To just topics? That’s rather interesting. That might mean that in your new action for your topic you’re not doing either:

@topic = Topic.new(:forum_id => params[:forum_id])

or
#this code I would move into a private method called find_forum

@forum = Forum.find(params[:forum_id])
@topic = @forum.topics.build

If you’re doing just Topic.new I think it’ll just redirect to /topics, but if you do it either of the ways I specified it should go to /forums/2/topics

I'll give the full code (after the modifications) cause I just don't
know what to do anymore I'm getting redirected to /topics with the
message `Couldn't find Forum without an ID`

here's the view:

<%= error_messages_for :topic %>
<%= error_messages_for :post %>

<%form_for @topic do |f| %>
<%= render :partial=>'topics/form',:locals=>{:f=>f} %>
<%fields_for @post do |p| %>
<fieldset class="alt">
  <%= render :partial=>'posts/form',:locals=>{:p=>p} %>
</fieldset>
<%end %>
<fieldset id="submit">
    <%= f.submit :create %>
</fieldset>
<%end %>

the controller:
class TopicsController < ApplicationController
  before_filter :user_logged_in?
  layout :switch_layout
  def index
    @topics = @forum.topics
  end

  def new
    @forum = Forum.find params[:forum_id]
    @topic =
Topic.new :forum_id=>params[:forum_id], :user_id=>session[:user_id]
    @post = Post.new
  end

  def create
    @forum = Forum.find(params[:forum_id])
    @topic = @forum.topics.build(params[:topic])
    @topic.posts.build(params[:post])
    @forum.save!

    flash[:notice] = 'Created new topic' if @topic.save!
    redirect_to forums_path
  rescue ActiveRecord::RecordInvalid
    render :action => :new
  end

  def edit
    @topic = Topic.find params[:id]
  end

  def update
    @topic = Topic.find params[:id]
    if @topic.update_attributes params[:topic]
      flash[:notice] = "Changed #{@topic.name}"
      redirect_to forum_path(@topic.forum_id)
    end
  rescue ActiveRecord::RecordInvalid
    render :action => :edit
  end

  def destroy
    topic =Topic.find params[:id]
    if topic.destroy
      flash[:notice] = "topic: #{topic.name} was deleted"
    end
    redirect_to forum_path(topic.forum_id)
  end

  def show
    @posts = Topic.find(params[:id]).posts
  end
end

Putting the forum aside I was trying to make a faq, type thing for my
project also using rest
so i went to the config/routes.rb typed
map.resources :subject, :has_many=>:faqs
map.resources :faqs

And when i'm trying to add a new faq to existing subject via
subjects/2/faqs/new
And when i'm sending the form it's redirected to /faqs with the same
error message :confused:

Ok resolved the address part the form_for method needs to look like
this
form_for[@subject,@faq] this is similar for the forum.