之前我們已經看到用腳手架運行的model程序。現在是時候第二個model了。
第二個model用來處理post的評論。
7.1 新建一個模型
Rails模型使用一個單一的的名稱,其相應的數據庫表使用復數名稱。
像模型來處理comments表,模型的名字所comment。即使你不想使用
腳手架來產生全部代碼。很多程序還是用generators來產生控制器和模型。
新建一個模型可以像下面一樣:運行命令。
- $ rails generate model Comment commenter:string body:text post:references
這個命令將會生成下面幾個文件
- app/models/comment.rb – 模型文件
- db/migrate/20100207235629_create_comments.rb – DB整合文件
- test/unit/comment_test.rb and test/fixtures/comments.yml –測試配置文件
首先我們看下模型文件
- class Comment < ActiveRecord::Base
- belongs_to :post
- end
這個和post.rb非常類似。不同點就是這有個belongs_to :post.
這是activerecord的關系設置。你將會在下面學到更多關於設定表之間的關系。
除了增加模型之外,rails還生成了創建表的整合代碼。
- class CreateComments < ActiveRecord::Migration
- def change
- create_table :comments do |t|
- t.string :commenter
- t.text :body
- t.references :post
- t.timestamps
- end
- add_index :comments, :post_id
- end
- end
t.references這行是設定和post模型的外鍵。
add_index這行是設定這個外鍵作為索引。
繼續向下進行db整合運行
- $ rake db:migrate
rails是足夠聰明的,他只運行DB中還沒有運行的整合。
- == CreateComments: migrating =================================================
- -- create_table(:comments)
- -> 0.0017s
- == CreateComments: migrated (0.0018s) ========================================
7.2 關聯模型
ActiveRecord可以讓你很簡單的設定2個模型之間的關系。在comments和posts2個模型之間,
你可以通過這個方式寫出他們的關系。
- 每個comment 屬於一個 post (1對1)
- 一個post 有很多的 comments (1對多)
事實上,rails使用非常接近的語法來聲明這種關系。你已經看到在comment模型代碼中,
聲明了每個comment屬於一個post。
- class Comment < ActiveRecord::Base
- belongs_to :post
- end
你需要編輯post.rb模型代碼來聲明上面的一對多關系。
- class Post < ActiveRecord::Base
- validates :name, :presence => true
- validates :title, :presence => true, :length => { :minimum => 5 }
- has_many :comments
- end
這2個聲明可以使用很多自動行為。例如:如果你有一個實例變量
@post包含 一個post,你可以取得所有屬於post的comments。通過
@post.comments方法返回一個數組。
7.3 給comments增加一個路由
像我們設置主頁一樣。我們需要增加一個路由來讓我們導航可以瀏覽
comments。打開config/routes.rb文件,你將會發現posts已經在里面了。
這是由腳手架自動生成的。編輯他們像下面一樣。
- resources :posts do
- resources :comments
- end
這個建立comments是一個posts的嵌套資源。這是捕捉post和comment之間存在層次關系的另一部分。
7.4 產生一個控制器
模型產生完之后。是時候產生對應的控制器了。
- $ rails generate controller Comments
這個命令產生了6個文件和一個空文件夾。
- app/controllers/comments_controller.rb – 控制器
- app/helpers/comments_helper.rb – 視圖的幫助文件
- test/functional/comments_controller_test.rb – 控制器的測試程序
- test/unit/helpers/comments_helper_test.rb – 幫助的測試代碼
- app/views/comments/ – 控制器的視圖代碼放在這
- app/assets/stylesheets/comment.css.scss – 控制器的樣式
- app/assets/javascripts/comment.js.coffee – 控制器的CoffeeScript
像很多博客一樣,我們的讀者將會創建評論在讀完博客之后。一旦他們評論完,
將會調用post的顯示頁面,可以看到他們的評論。根據這些,我們的CommentsController
應該提供創建評論和刪除垃圾評論的方法。
所以首先我們修改post的顯示頁面(/app/views/posts/show.html.erb)可以讓我們增加評論。
- <p class="notice"><%= notice %></p>
- <p>
- <b>Name:</b>
- <%= @post.name %>
- </p>
- <p>
- <b>Title:</b>
- <%= @post.title %>
- </p>
- <p>
- <b>Content:</b>
- <%= @post.content %>
- </p>
- <h2>Add a comment:</h2>
- <%= form_for([@post, @post.comments.build]) do |f| %>
- <div class="field">
- <%= f.label :commenter %><br />
- <%= f.text_field :commenter %>
- </div>
- <div class="field">
- <%= f.label :body %><br />
- <%= f.text_area :body %>
- </div>
- <div class="actions">
- <%= f.submit %>
- </div>
- <% end %>
- <%= link_to 'Edit Post', edit_post_path(@post) %> |
- <%= link_to 'Back to Posts', posts_path %> |
這個加進去的form是新建一個新的評論,將會調用
CommentsController的create方法。
- class CommentsController < ApplicationController
- def create
- @post = Post.find(params[:post_id])
- @comment = @post.comments.create(params[:comment])
- redirect_to post_path(@post)
- end
- end
你會看到這里面的處理會比post控制器的處理稍微復雜一點。這個設置了一個嵌套機制。每個評論都會跟隨post。
所以在一開始進行了Post的查找。
同時,代碼使用了模型關聯的一些方法。我們使用@post.comments的create方法來新建保存評論。
這個將會自動連接comment因為他從屬於post。
一旦我們新建完評論,我們將用戶回到原來的頁面通過post_path(@post)。
正如我們所看到的,他將會調用PostsController的show動作,這時候我們希望
評論顯示在此頁面上。所以我們修改頁面代碼。
- <p class="notice"><%= notice %></p>
- <p>
- <b>Name:</b>
- <%= @post.name %>
- </p>
- <p>
- <b>Title:</b>
- <%= @post.title %>
- </p>
- <p>
- <b>Content:</b>
- <%= @post.content %>
- </p>
- <h2>Comments</h2>
- <% @post.comments.each do |comment| %>
- <p>
- <b>Commenter:</b>
- <%= comment.commenter %>
- </p>
- <p>
- <b>Comment:</b>
- <%= comment.body %>
- </p>
- <% end %>
- <h2>Add a comment:</h2>
- <%= form_for([@post, @post.comments.build]) do |f| %>
- <div class="field">
- <%= f.label :commenter %><br />
- <%= f.text_field :commenter %>
- </div>
- <div class="field">
- <%= f.label :body %><br />
- <%= f.text_area :body %>
- </div>
- <div class="actions">
- <%= f.submit %>
- </div>
- <% end %>
- <br />
- <%= link_to 'Edit Post', edit_post_path(@post) %> |
- <%= link_to 'Back to Posts', posts_path %> |
這樣的話,你可以增加博客和評論,他們可以顯示在正確的位置