用Rails实现一个简单的论坛系统,大致的架构为:站点拥有多个Forum,每个Forum有多个Topic,而每个Topic又有多个Reply。原文链接:
http://railsonedge.blogspot.com/2008/02/rails-forum-tutorial-for-beginners-part.html。
我下载的是目前最新的Rails版本2.1,数据库使用的是Sql Server 2000,应用程序所在目录为F:\Ruby\railsdoc\myforum。首先快速地依照以下步骤创建Forum类:
- 执行rails myforum生成完整的目录结构;
- 执行ruby script/generate scaffold Forum name:string description:text创建相关的数据库移植文件及model、controller、views文件;
- 修改database.yml文件中的相关数据库配置信息;
- 在Sql Server中新建名为myforum的数据库,并执行rake db:migrate创建forums表;
- 修改environment.rb文件使页面能正常显示中文。
这样Forum页面就完成了,启动服务器后在浏览器键入http://127.0.0.1:3000/forums便能进行CRUD操作了。
删除/public/index.html,修改/config/routes.rb,使得http://localhost:3000直接指向Forum列表:
引用
map.root :controller => 'forums', :action => 'index'
分别执行以下命令创建Topic和Reply的相关文件及数据库表:
引用
ruby script/generate scaffold Topic forum:references user:references subject:string body:text
ruby script/generate scaffold Reply topic:references user:references subject:string body:text
rake db:migrate
表Forum
表Topic
表Reply
修改/config/routes.rb
……
map.resources :forums, :has_many => :topics # Add
map.resources :topics, :has_many => :replies # Add
map.resources :replies
……
修改/app/models/forum.rb
class Forum < ActiveRecord::Base
has_many :topics # Add
has_many :replies, :through => :topics # Add
end
修改/app/models/topic.rb
class Topic < ActiveRecord::Base
belongs_to :forum # Add
belongs_to :user # Add
has_many :replies # Add
end
修改/app/models/reply.rb
class Reply < ActiveRecord::Base
belongs_to :topic # Add
belongs_to :user # Add
end
修改/app/controllers/topics_controller.rb
class TopicsController < ApplicationController
before_filter :load_forum # Add
def load_forum # Add
@forum = Forum.find(params[:forum_id]) # Add
end # Add
# GET /topics
# GET /topics.xml
def index
@topics = @forum.topics # Edit: @topics = Topic.find(:all)
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @topics }
end
end
# GET /topics/1
# GET /topics/1.xml
def show
@topic = @forum.topics.find(params[:id]) # Edit: @topic = Topic.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @topic }
end
end
# GET /topics/new
# GET /topics/new.xml
def new
@topic = @forum.topics.build # Edit: @topic = Topic.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @topic }
end
end
# GET /topics/1/edit
def edit
@topic = @forum.topics.find(params[:id]) # Edit: @topic = Topic.find(params[:id])
end
# POST /topics
# POST /topics.xml
def create
@topic = @forum.topics.build(params[:topic]) # Edit: @topic = Topic.new(params[:topic])
respond_to do |format|
if @topic.save
flash[:notice] = 'Topic was successfully created.'
format.html { redirect_to(@forum) } # Edit: format.html { redirect_to(@topic) }
format.xml { render :xml => @topic, :status => :created, :location => @topic }
else
format.html { render :action => "new" }
format.xml { render :xml => @topic.errors, :status => :unprocessable_entity }
end
end
end
# PUT /topics/1
# PUT /topics/1.xml
def update
@topic = @forum.topics.find(params[:id]) # Edit: @topic = Topic.find(params[:id])
respond_to do |format|
if @topic.update_attributes(params[:topic])
flash[:notice] = 'Topic was successfully updated.'
format.html { redirect_to(@forum) } # Edit: format.html { redirect_to(@topic) }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => @topic.errors, :status => :unprocessable_entity }
end
end
end
# DELETE /topics/1
# DELETE /topics/1.xml
def destroy
@topic = @forum.topics.find(params[:id]) # Edit: @topic = Topic.find(params[:id])
@topic.destroy
respond_to do |format|
format.html { redirect_to(forum_topics_url(@forum)) } # Edit: format.html { redirect_to(topics_url) }
format.xml { head :ok }
end
end
end
以上修改基于两个目的:一、使得对于Topic的操作能关联到正确的外键(forum_id),二、在对Topic执行CUD操作后将能返回至相应的Forum页面,而不是Topic页面。
将/app/views/forums/show.html.erb
<p>
<b>Name:</b>
<%=h @forum.name %>
</p>
<p>
<b>Description:</b>
<%=h @forum.description %>
</p>
<%= link_to 'Edit', edit_forum_path(@forum) %> |
<%= link_to 'Back', forums_path %>
修改为
<p>
<b>Forum:</b>
<%=h @forum.name %> - <%=h @forum.description %>
</p>
<% unless @forum.topics.empty? %>
<h2>Topics</h2>
<% @forum.topics.each do |topic| %>
<b><%= link_to topic.subject, [@forum, topic] %></b><br />
<% end %>
<% end %>
<h2>New Post</h2>
<%= render :partial => @topic = Topic.new, :locals => { :button_name => 'Create' } %>
<%= link_to 'Edit', edit_forum_path(@forum) %> |
<%= link_to 'Back', forums_path %>
可以看到/app/views/topics/new.html.erb和/app/views/topics/edit.html.erb相当类似,我们创建一个新的文件/app/views/topics/_topic.html.erb
<% form_for([@forum, @topic]) do |f| %>
<p>
<b>Subject</b><br />
<%= f.text_field :subject %>
</p>
<p>
<b>Body</b><br />
<%= f.text_area :body %>
</p>
<p>
<%= f.submit button_name %>
</p>
<% end %>
将/app/views/topics/new.html.erb
<h1>New topic</h1>
<% form_for(@topic) do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :forum %><br />
<%= f.text_field :forum %>
</p>
<p>
<%= f.label :user %><br />
<%= f.text_field :user %>
</p>
<p>
<%= f.label :subject %><br />
<%= f.text_field :subject %>
</p>
<p>
<%= f.label :body %><br />
<%= f.text_area :body %>
</p>
<p>
<%= f.submit "Create" %>
</p>
<% end %>
<%= link_to 'Back', topics_path %>
修改为
<h1>New topic</h1>
<%= error_messages_for :topic %>
<%= render :partial => @topic, :locals => { :button_name => "Create" } %>
<%= link_to 'Back', topics_path %>
将/app/views/topics/edit.html.erb
<h1>Editing topic</h1>
<% form_for(@topic) do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :forum %><br />
<%= f.text_field :forum %>
</p>
<p>
<%= f.label :user %><br />
<%= f.text_field :user %>
</p>
<p>
<%= f.label :subject %><br />
<%= f.text_field :subject %>
</p>
<p>
<%= f.label :body %><br />
<%= f.text_area :body %>
</p>
<p>
<%= f.submit "Update" %>
</p>
<% end %>
<%= link_to 'Show', @topic %> |
<%= link_to 'Back', topics_path %>
修改为
<h1>Editing topic</h1>
<%= error_messages_for :topic %>
<%= render :partial => @topic, :locals => { :button_name => "Submit" } %>
<%= link_to 'Show', [@forum, @topic] %> |
<%= link_to 'Back', topics_path %>
目前部分已完成Forum和Topic的关联,以下是操作页面截图:
Forum List
Topic List
Topic Details