ผลต่างระหว่างรุ่นของ "418342 ภาคปลาย 2552/การบ้าน 3"

จาก Theory Wiki
ไปยังการนำทาง ไปยังการค้นหา
แถว 131: แถว 131:
 
== การบ้านข้อ 3: แก้ Post Controller ==
 
== การบ้านข้อ 3: แก้ Post Controller ==
 
=== แก้ show ของ PostsController ===
 
=== แก้ show ของ PostsController ===
ให้เปลี่ยน app/views/posts/show.html.erb ให้เขียนโค้ด HTML ออกมาลักษณะตามข้างล่างนี้
+
ให้เปลี่ยน app/views/posts/show.html.erb ให้เขียนโค้ด HTML ที่มีการแสดงข้อมูลต่อไปนี้
<geshi lang="rails">
+
* หัวเรื่องของโพสต์
<div class="post" id="post_{{รหัสโพสต์}}">
+
* เนื้อหาโพสต์
  <h2>{{หัวเรื่องของโพสต์}}</h2>
+
* วันที่เขียน
  {{เนื้อหาของโพสต์ที่่ผ่านการแปลด้วย Markdown แล้ว​​​​}}
+
* แท็กต่างๆ ของโพสต์
  <p>
+
* ลิงค์ Edit และ Back ที่ได้มาจาก scaffold
    <small>     
+
* จำนวนคอมเมนต์
        Posted on {{วันที่พิมพ์}}<br/>     
+
* คอมเมนต์เรียงจากเก่าไปใหม่
        Tags: <-- ถ้าไม่มี tag สักตัวจะต้องไม่มีส่วนนี้
+
* แบบฟอร์มสำหรับให้ผู้ใช้กรอกคอมเมนต์
          {{ระบุ tag พร้อมทั้ง link ถึงมัน ทีละตัวๆ คั่นด้วยคอลัมน์และช่องว่าง}}
 
    </small>
 
  </p>
 
</div>
 
<a href="/posts/32/edit">Edit</a> |
 
<a href="/posts">Back</a>
 
</geshi>
 
ยกตัวอย่างเช่น
 
<geshi lang="rails">
 
<div class="post" id="post_32">
 
  <h2>Post #3</h2>
 
  
  <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit</p>
+
จงทำให้แบบฟอร์มในการกรอกคอมเมนต์นี้ทำงานได้ถูกต้อง
  
  <p>
+
=== แก้ไข index ของ PostsController ===
    <small>     
+
ให้เปลี่ยน app/views/posts/index.html.erb ให้เขียนโค้ด HTML ทีมีการแสดงข้อมูลดังนี้
        Posted on 21 February 2010<br/>     
+
* แสดงโพสต์ใหม่ล่าสุดเท่ากับจำนวน posts_per_page ที่เก็บไว้ใน Setting
        Tags:
+
* สำหรับแต่ละโพสต์ ให้มีการแสดง
          <a href="/tags/1">dog</a>,
+
** วันที่เขียน
          <a href="/tags/3">sea otter</a>
+
** หัวเรื่อง ซึ่งมีลิงค์ไปยังหน้า show ของโพสต์นั้น
    </small>
+
** เนื้อหาโพสต์
  </p>
+
** แท็กต่างๆ ของโพสต์
</div>
+
** จำนวนคอมเมนต์ ซึ่งมีลิงค์ไปยังหน้า show ของโพสต์นั้น แต่เมื่อตามลิงค์ไปแล้วให้ไปอยู่ตรงที่ตำแหน่งเริ่มคอมเมนต์พอดี
<a href="/posts/32/edit">Edit</a> |
+
 
<a href="/posts">Back</a>
+
ในการแสดงโพสต์ใหม่ล่าสุดนี้ คุณจะต้องแสดง
</geshi>
+
* โพสต์ที่ published_at มีค่าไม่เป็นค่าว่าง
 +
* เรียงโพสต์ตาม published_at จากใหม่สุดไปยังเก่าสุด
 +
* มีลิงค์ให้ผู้ใช้คลิกเพื่ออ่านโพสต์เก่าขึ้นหรือไม่ขึ้นที่อยู่ในหน้าถัดไป (เหมือนบล็อกทั่วๆ ไป)

รุ่นแก้ไขเมื่อ 01:08, 25 กุมภาพันธ์ 2553

(กำลังเขียนอยู่)​ ในการบ้านนี้เราจะทำการสร้างระบบบล็อกเบื้องต้นที่มีฟีเจอร์ดังต่อไปนี้

  • มีหน้าหลักแสดงโพสต์ล่าสุด
  • มีระบบให้ผู้อ่านมาพิมพ์คอมเมนต์
  • ผู้เขียนสามารถตั้งค่าต่างๆ ของบล็อก เช่น ชื่อบล็อก, จำนวนโพสต์ที่แสดงในแต่ละหน้า, ฯลฯ
  • ผู้เขียนสามารถแท็กบทความต่างๆ ได้

เริ่มต้น

  • ให้ดาวน์โหลดโค้ดเริ่มต้นจาก ... ในโค้ดเริ่มต้นนี้จะมี scaffold ซึ่งสร้างตามฐานข้อมูลที่เขียนไว้ข้างล่าง พร้อมกับข้อมูลทดสอบส่วนหนึ่งอยู่
  • ให้ลงไลบรารี Maruku ซึ่งเป็นตัวแปรภาษา Makrdown ที่เราจะใช้ในการเขียนเนื้อหาของบล็อก ด้วยการสั่ง
gem install maruku

ฐานข้อมูล

ฐานข้อมูลของระบบบล็อกจะประกอบด้วยตารางต่อไปนี้

ตาราง posts

เก็บโพสต์ของเจ้าของบล็อก มีฟีลด์ดังต่อไปนี้

  • title เป็น string
  • content เป็น text ซึ่งเขียนด้วยภาษา Markdown
  • published_at เป็น datetime ซึ่งจะมีค่าเป็น nil ถ้าหากผู้ใช้ยังไม่ได้ตีพิมพ์โพสต์นี้
  • timestamp (created_at และ modified_at) ซึ่งสร้างด้วย t.timestamp ใน migration

ตาราง comments

เก็บคอมเมนต์ที่มีคนมาเขียน มีฟีลด์ดังต่อไปนี้

  • name เป็น string เก็บชื่อคนเขียน comment
  • email เป็น string เก็บ email ของคนเขียน comment
  • url เป็น string เก็บ URL ของเว็บไซต์ของคนเขียน comment
  • content เป็น text ซึ่งเขียนด้วยภาษา Markdown เช่นกัน
  • post_id เป็น integer ซึ่งเก็บ id ของ post ที่ comment
  • timestamp (created_at และ modified_at) ซึ่งสร้างด้วย t.timestamp ใน migration

ตาราง tags

เก็็บ tag ต่างๆ มีฟีลด์ดังต่อไปนี้

  • name เป็น string ซึ่งเป็นชื่อของ tag

ตาราง posts_tags

ใช้ในการทำความสัมพันธ์แบบ many-to-many ระหว่าง post กับ tag มีฟีลด์ดังต่อไปนี้

  • post_id
  • tag_id

ตาราง settings

เก็บค่าต่างๆ ที่ผู้ใช้สามารถกำหนดให้บล็อกได้ เช่น ชื่อบล็อก ฯลฯ มีฟีลด์ดังต่อไปนี้

  • name เป็น string ซึ่งเป็นชื่อของค่าที่ผู้ใช้กำหนดได้
  • value เป็น string ซึ่งเก็บค่าจริง

ในตาราง settings จะมีค่าต่อไปนี้อยู่

  • blog_name = ชื่อของบล็อก (จะปรากฏอยู่ที่หัวเว็บเพจ)
  • blog_subtitle = คำอธิบายบล็อกสั้นๆ (จะปรากฏอยู่ที่หัวเว็บเพจเช่นกัน)
  • blog_url = URL ของบล็อกซึ่งมีไว้ใช้ทำ RSS feed
  • posts_per_page = จำนวนบล็อกในแต่ละหน้า
  • comment_count = จำนวนคอมเมนต์เริ่มต้นที่แสดงเวลาดูโพสต์

การบ้านข้อ 1: แก้ไขโมเดล

แก้ไข Post

  1. ทำให้ Post มีความสัมพันธ์แบบ many-to-many กับ Tag
  2. ทำให้ Post มีความสัมพันธ์แบบ many-to-one กับ Comment
  3. เขียน validation ทำให้ Post สอดคล้องกับเงื่อนไขต่อไปนี้
    • title จะต้องไม่ว่างเปล่า
    • content จะต้องไม่ว่างเปล่า
  4. เขียนเมธอดชื่อ published? เพื่อเช็คว่าผู้ใช้ได้ตีพิมพ์โพสต์ไปแล้วหรือยัง โดย method จะเช็คว่า published_at มีค่าเป็น nil หรือไม่ ถ้าใช่แสดงว่ายังไม่ได้ตีพิมพ์

เมื่อคุณแก้โค้ดตามนี้แล้ว ให้ลองรัน

rake test:units TEST=unit/test/post_test.rb

เพื่อตรวจสอบว่าได้แก้ไขไปถูกต้องแล้วหรือไม่

แก้ไข Comment

เขียน validation ทำให้ Comment สอดคล้องกับเงื่อนไขต่อไปนี้

  • name จะต้องไม่ว่างเปล่า
  • email จะต้องมีรูปแบบเหมือน email ​(ใบ้: ใช้ validate_format_of)
  • url จะต้องมีรูปแบบเหมือน URL จริงๆ (คือ http://something.someone.org/abc/def) (ใบ้: ไปหา regular expression มาจากใน net)
  • content จะต้องไม่ว่างเปล่า

เมื่อคุณแก้โค้ดตามนี้แล้ว ให้ลองรัน

rake test:units TEST=unit/test/comment_test.rb

เพื่อตรวจสอบว่าได้แก้ไขไปถูกต้องแล้วหรือไม่

แก้ไข Tag

เขียน validation

ทำให้ Tag ที่มีรูปแบบถูกต้องทุกตัวสอดคล้องกับเงื่อนไขต่อไปนี้

  • name จะต้องไม่ว่างเปล่า
  • ใน name จะต้องไม่มีเครื่องหมายคอมมา (,) อยู่ภายใน (เนื่องจากเราใจใช้เครื่องหมายนี้ในการแยก tag ต่างๆ ออกจากกัน) กล่าวคือ "space adventure" ใช้ได้ แต่ "space,adventure" หรือ "space, adventure" ใช้ไม่ได้

ทำให้ชื่อ Tag อยู่ในรูป "ปกติ"

เราต้องการให้เวลาเจ้าของบล็อกใส่ tag ให้โพสต์ แล้วเขาสามารถพิมพ์ "life, space adventure, computer   security " แล้วระบบสามารถที่จะแยกมันออกเป็น 3 tag ได้แก่ "life", "space adventure", และ "computer security" ให้โดยอัตโนมัติ

เนื่องจากเราบอกว่าชื่อแท็กจะต้องไม่มีเครื่องหมายคอมมาอยู่ข้างใน ดังนั้นเราสามารถแยก string ที่ผู้ใช้ให้มาข้างบนเป็นสามส่วนคือ "life" และ " space adventure" และ " computer   security "

เวลาเราเก็บชื่อของ Tag ใน database เราต้องการกำจัดข้อมูลที่ไม่สำคัญออกจากชื่อ Tag ที่ผู้ใช้ป้อนมาไป ยกตัวอย่างเช่น ผู้ใช้ป้อน " computer   security " ซึ่งมีช่องว่างอยู่ข้างหน้าชื่อ ข้างหลังชื่อ และช่องว่างระหว่างคำว่า computer กับคำว่า security มีอยู่ถึงสามตัว แต่ในเวลาเก็บข้อมูลเราต้องการให้ชื่อมีค่าเท่ากับ "computer security" เท่านั้น กล่าวคือ

  • จะต้องไม่มีช่องว่างนำหน้าชื่อ Tag
  • จะต้องไม่มีช่องว่างตามหลังชื่อ Tag
  • ระหว่างคำสองคำที่อยู่ข้างๆ กันในชื่อ Tag จะมีช่องว่างคั่นได้เพียงช่องเดียวเท่านั้น

เราเรียกชื่อที่สอดคล้องกับกฎทั้งสามข้อข้างต้นว่าเป็นชื่อ Tag ในรูป "ปกติ"

ตรวจสอบความถูกต้อง

จงเพิ่มคลาสเมธอด normalize_name(given_name) ในคลาส Tag โดยที่เมธอดนี้ืคืนค่าของ given_name เมื่อทำให้มันอยู่ในรูปปกติแล้ว

เวลาประกาศคลาสเมธอดให้ประกาศเช่นนี้ <geshi lang="rails"> class Tag

 ...
 def Tag.normalize_name(given_name)
   ...
 end
 ...

end </geshi>

เมื่อคุณแก้โค้ดตามนี้แล้ว ให้ลองรัน

rake test:units TEST=unit/test/tag_test.rb

เพื่อตรวจสอบว่าได้แก้ไขไปถูกต้องแล้วหรือไม่

แก้ไข Setting

จงเขียน validation เพื่อทำให้ Setting ทุกตัวสอดคล้องกับเงื่อนไขต่อไปนี้

  • name จะต้องไม่เป็นค่าว่าง
  • value จะต้องไม่เป็นค่าว่าง
  • ถ้า name มีค่าเท่ากับ "posts_per_page" หรือ ​"comment_count" แล้ว value จะต้องเป็นสตริงที่มีค่าเป็นตัวเลข

เมื่อคุณแก้โค้ดตามนี้แล้ว ให้ลองรัน

rake test:units TEST=unit/test/setting_test.rb

เพื่อตรวจสอบว่าได้แก้ไขไปถูกต้องแล้วหรือไม่

การบ้านข้อ 2: ทำให้ Markdown ใช้ได้

แก้ไข Post

ให้สร้างเมธอดชื่อ markdowned_content ซึ่งคืนค่า content ที่ถูกแปลด้วยภาษา Markdown แล้ว ในการแปลให้ใช้ไลบรารีชื่อ Maruku ซึ่งมีวิธีใช้บอกอยู่ในเอกสารนี้ http://maruku.rubyforge.org/usage.html

เมื่อคุณแก้โค้ดตามนี้แล้ว ให้ลองรัน

rake test:units TEST=unit/test/markdown_post_test.rb

เพื่อตรวจสอบว่าได้แก้ไขไปถูกต้องแล้วหรือไม่

แก้ไข Comment

สำหรับโมเดล Comment ก็ให้สร้างเมธอดชื่อ markdowned_content ซึ่งทำงานเช่นเดียวกันกับ markdowned_content ของ Post เช่นกัน

เมื่อคุณแก้โค้ดตามนี้แล้ว ให้ลองรัน

rake test:units TEST=unit/test/markdown_comment_test.rb

เพื่อตรวจสอบว่าได้แก้ไขไปถูกต้องแล้วหรือไม่

การบ้านข้อ 3: แก้ Post Controller

แก้ show ของ PostsController

ให้เปลี่ยน app/views/posts/show.html.erb ให้เขียนโค้ด HTML ที่มีการแสดงข้อมูลต่อไปนี้

  • หัวเรื่องของโพสต์
  • เนื้อหาโพสต์
  • วันที่เขียน
  • แท็กต่างๆ ของโพสต์
  • ลิงค์ Edit และ Back ที่ได้มาจาก scaffold
  • จำนวนคอมเมนต์
  • คอมเมนต์เรียงจากเก่าไปใหม่
  • แบบฟอร์มสำหรับให้ผู้ใช้กรอกคอมเมนต์

จงทำให้แบบฟอร์มในการกรอกคอมเมนต์นี้ทำงานได้ถูกต้อง

แก้ไข index ของ PostsController

ให้เปลี่ยน app/views/posts/index.html.erb ให้เขียนโค้ด HTML ทีมีการแสดงข้อมูลดังนี้

  • แสดงโพสต์ใหม่ล่าสุดเท่ากับจำนวน posts_per_page ที่เก็บไว้ใน Setting
  • สำหรับแต่ละโพสต์ ให้มีการแสดง
    • วันที่เขียน
    • หัวเรื่อง ซึ่งมีลิงค์ไปยังหน้า show ของโพสต์นั้น
    • เนื้อหาโพสต์
    • แท็กต่างๆ ของโพสต์
    • จำนวนคอมเมนต์ ซึ่งมีลิงค์ไปยังหน้า show ของโพสต์นั้น แต่เมื่อตามลิงค์ไปแล้วให้ไปอยู่ตรงที่ตำแหน่งเริ่มคอมเมนต์พอดี

ในการแสดงโพสต์ใหม่ล่าสุดนี้ คุณจะต้องแสดง

  • โพสต์ที่ published_at มีค่าไม่เป็นค่าว่าง
  • เรียงโพสต์ตาม published_at จากใหม่สุดไปยังเก่าสุด
  • มีลิงค์ให้ผู้ใช้คลิกเพื่ออ่านโพสต์เก่าขึ้นหรือไม่ขึ้นที่อยู่ในหน้าถัดไป (เหมือนบล็อกทั่วๆ ไป)