FeaturesDocs & SupportCommunityBlogsPartners

构建 Rails 模型之间的关系

本教程介绍如何在 NetBeans Ruby on Rails 项目中构建模型之间的关系(一对一和多对一)。

目录

教程需求
创建样例数据库
创建评论模型
迁移数据库
定义评论模型和文章模型之间的关系
修改控制器脚手架
修改视图以添加评论
显示评论
  本页面的内容适用于 NetBeans IDE 6.0

教程需求

学习本教程需要以下技术和资源:

创建样例数据库

本教程基于教程 10 分钟创建 Ruby Weblog。如果您完成了那篇教程,那么您可以将完成教程时生成的项目作为起点,直接进入下一节。否则,请您先下载 RubyWebLog.zip 文件,然后按照下面的步骤创建样例数据库。

 

注意:本教程使用 MySQL 数据库服务器。您可以参考安装和配置 Ruby 支持一文以获取有关如何在 Ruby 应用程序中使用 MySQL 数据库服务器的信息。该文档同样介绍了如何使用 JavaDB 数据库服务器作为替代。
  1. 打开一个命令行窗口。
  2. 如果 MySQL 数据库服务器尚未被启动,请先将其启动。
  3. 键入如下命令来创建开发数据库,并按“Enter”键。
    mysqladmin -u root -p create rubyweblog_development
    注意:如果 root 用户不要求密码,请省略 -p 参数。
  4. 在 IDE 中打开 rubyweblog 项目。

    注意:如果是初次打开或者创建 Ruby 项目,IDE 会检查您是否有除了绑定的 JRuby 软件之外其他的 Ruby 安装。如果有,IDE 会显示一个对话框,询问您选择使用哪个软件。若您想要使用绑定的 JRuby 解释器,选择 JRuby;或者您喜欢使用您自己的 Ruby 安装,那就选择您自己的安装。更多信息,请参考《安装和配置 Ruby》教程中的配置 IDE 使用您自己的 Ruby 安装一节。
  5. 如果您的数据库要求密码,请编缉 database.yml 文件,并在开发配置部分中提供密码。保存该文件。

    要快速访问 database.yml 文件,按 Alt+Shift+O(在 Mac 系统中按 Ctrl+Shift+O),在“文件名”文本框中键入 database.yml,然后按“Enter”键。
  6. 右键点击 rubyweblog 节点,选择“迁移数据库”>“到当前版本”。

    该操作会更新数据库以加入 posts 表并添加 body 字段。 迁移完成时会在“输出”窗口显示。
  7. 运行应用程序并发表一篇新文章。

创建评论模型

本教程通过增加允许读者给 blog 文章添加评论的功能扩充 rubyweblog 项目。首先要创建评论模型来存储读者评论实例。而此项目中已经有了存储 blog 文章实例的文章模型。
  1. 在“项目”窗口中,展开“rubyweblog”节点,右键点击“Models”节点,然后选择“Generate”。

  2. 在“Arguments”字段中键入 Comment post_id:integer created_at:datetime comment:text,然后点击“OK”。

    “Rails Generator”会创建一个名为“Comment”的模型。该模型包含如下文件:

    • app/models/comment.rb 存有评论模型方法的文件。此文件已在编辑区中打开。
    • test/unit/comment_test.rb 用于检测模型的单元测试。
    • test/fixtures/comments.yml 用于填充模型的测试套件
    • db/migrate/migrate/003_create_comments.rb 更改数据库结构的迁移文件。 该文件的版本为003,这是因为项目已经有了两个迁移文件:001_create_posts.rb002_add_body.rb,他们用于创建和修改 posts 表。

迁移数据库

接下来要处理的文件就是迁移文件 003_create_comments.rb 了。
  1. 在“输出”窗口中,点击 003_create_comments.rb 文件的链接。

    文件打开后会显示 self.up 方法(创建 comments 表)和 self.down 方法(删除 comments 表),如下列代码示例所示:

     

    代码示例 1:comments 表的迁移代码
    class CreateComments < ActiveRecord::Migration
    def self.up
    create_table :comments do |t|
    t.column :post_id, :integer
    t.column :created_at, :datetime
    t.column :comment, :text
    end
    end

    def self.down
    drop_table :comments
    end
    end

    此段迁移代码会创建一张含有 4 个字段 comments 表:id,整数;post_id,整数;created_at,存储日期时间;comment,文本描述。
  2. 右键点击 rubyweblog 节点,选择“迁移数据库”>“到当前版本”。

    该操作会更新数据库以加入 comments 表。 迁移完成时会在“输出”窗口显示。

定义评论模型和文章模型之间的关系

应用程序目前有两个模型:文章模型发表一篇新的 blog 文章,而评论模型则向一篇 blog 文章添加一条评论。现在给两个模型之间定义关系, 使得一条评论关联一篇文章,而一篇文章可以包含多条评论。
  1. 展开“Models”节点,打开 post.rb
  2. post.rb 中添加如下 has_many 关联:

    代码示例 2:post.rb 中的 has_many 关联
    class Post < ActiveRecord::Base
    validates_presence_of :title, :body
    has_many :comments
    end

    has_many 方法表明文章可以有 0 个、1 个或者多个评论记录与之关联。

    小贴士: 键入触发器 hm后按 Tab 键,可以扩展成代码模板 has_many :objects
  3. 打开“Models”> comment.rb,然后添加 belongs_to 关联:

    代码示例 3:comment.rb 中的 belongs_to 关联

    class Comment < ActiveRecord::Base
    belongs_to :post
    end

    belongs_to 方法表明一条评论只能和一篇文章相关联。ActiveRecord 默认使用 post_id 来将一条评论和有相应 post.id 的文章进行关联。

    小贴士:bt 触发器能扩展成 belongs_to :object

修改控制器脚手架

接下来处理控制器,blog_controller.rb,它能生成用于在 blog 文章中创建、读取、更新和删除条目的脚手架或者基本接口。
  1. 展开“Controllers”节点,打开 blog_controller.rb

    控制器拥有所有的脚手架动作,包括 indexlistshownewcreateeditupdatedestroy
  2. 如下面的代码示例所示,修改 show 动作,将 post_id 保存到 flash 中:

    代码示例 4:show 动作
    def show
    @post = Post.find(params[:id])
    flash[:post_id] = @post.id
    end

    此段代码查找与请求中所传的参数 id 相关联的文章。然后把 id 存放到 flash 中以备后用。flash 类似于 HTTP 会话,但可以跨越单个请求。当在 flash 中放入一个物品时,该物品对下个请求可用,但然后就消失了(因此使用术语“flash”称之)。
  3. 滚动至 blog_controller.rb 文件的结尾处,然后在最后的 end 语句前添加如下 post_comment 动作:

    代码示例 5:post_comment 动作

    def post_comment
    @comment = Comment.new(
    "post_id" => flash[:post_id],
    "created_at" => Time.now,
    "comment" => params[:comment]['comment']
    )
    if @comment.save
    flash[:notice] = 'Comment was successfully added.'
    redirect_to :action => 'show', :id => flash[:post_id]
    end
    end

    当用户点击“Post”按钮提交评论时就会调用 post_comment 动作。此段代码的第一段从 flash 中获取 post_id(1, 2, ...),并使用该 id 查找与之相关联的 blog 文章。紧接着代码会创建一个新的评论对象来关联该 post_id,组成部分还包括创建时间和实际评论。Rails 框架把从页面提交的参数作为散列来传递(params[:comment]),通过该散列码能够取出评论参数(params[:comment]['comment'])。

    由于评论(Comment)是一个 ActiveRecord 类,故调用其 save 方法可以将评论记录保存到数据库中。接着把成功保存记录的消息放到 flash 中。代码然后调用 show 动作,载入 show.rhtml 页面。该页面将重新载入文章和与它相关的所有评论,包括新添加的那条。

修改视图以添加评论

编缉 show.rhtml 文件,显示单独的 blog 条目。
  1. 展开“Views”> blog,然后打开 show.rhtml
  2. show.rhtml 文件末尾添加下列代码:

    代码示例 6:show.rhtml 所需代码

    <hr>
    <h4>Comments</h4>

    <% form_tag :action => 'post_comment' do %>
    <p><label for="comment_comment">Comment</label><br/>

    <%= text_area 'comment', 'comment' %></p>
    <%= submit_tag "Post" %>
    <%end %>

    此段代码产生一个表单,包括一个用于编写评论的文本输入区,和一个标识为 Post 的提交按钮,如图 1 所示。表单提交时会调用 post_comment 动作。
  3. 保存文件,然后运行应用程序。
  4. 点击“Permalink”查看 blog 条目的详细信息。 试着在文本区添加一条评论,但是请留意当点击“Post”按钮时 blog 还不能显示评论。

    如果您的提交成功了,您可以看到视图顶部会有一条消息,如下图所示。后面几个步骤,我们将添加代码来收集并显示这些评论。

    图 1:没有显示评论的评论模型视图

    没有显示评论的评论模型视图

显示评论

blog 目前还不能显示读者添加的评论,所以现在来解决这个问题。
  1. blog_controller.rb 中查找 show 动作,然后插入下面的 post_comments 实例变量来收集评论。

    代码示例 7:blog_controller.rb 所需代码

    def show
    @post = Post.find(params[:id])
    @post_comments = @post.comments.collect
    flash[:post_id] = @post.id
    end

    由于给文章模型添加了 has_many :comments 关系,可以通过调用 @post.comments 来访问一篇文章的所有评论。
  2. 修改 show.rhtml,将下面 <ul> 标签的内容复制粘贴到 <h4>Comments</h4> 行下面:

    代码示例 8:show.rhtml 所需代码
    <ul>

    <% @post_comments.each do |comment| %>
    <li><%= h comment.comment %><br>
    <div style="color: #999; font-size: 8pt">
    Posted on <%= comment.created_at.strftime("%B %d, %Y at %I:%M %p") %>
    </div>

    </li>
    <% end %>
    </ul>

    此段代码设定评论显示风格,以符合列表显示评论,同时加入评论发表的日期和时间。
  3. 选择“文件”>“全部保存”,然后刷新浏览器。

    现在评论就以符号列表的形式显示在 blog 中了,如下图所示。

    图 2:显示评论的评论模型视图

    图 2:显示评论的评论模型视图

更多内容

Companion
Projects:
                  Powered by: