Ruby on Rails :: Hello, Rails!(2)

Posted by PunNeng, Tue Jun 20 23:55:00 UTC 2006

จากครั้งที่แล้ว มันดูนิ่งๆ น่าเบื่อที่สุด มาทำให้มันสนุกดีกว่า ต่อไปจะร่ายเวทย์เล็กๆ น้อยๆ ให้ดูแล้วนะครับ ในการทำอันนี้ เราจะต้องแก้ไขใน file ใน views โดยจะใส่เวลาเข้าไป โดยให้มันแสดงเวลาตอนนี้ ตอนที่มันถูกเรียก อ่าาาา เกิดคำถามมาสองคำถามคือ เราจะเพิ่ม dynamic content นี้ได้ยังไง และ เราจะเอาเวลาที่จะแสดงมาจากไหน

Dynamic Content

มีสองทางในการสร้าง dynamic content ใน Rails คือ การเรียกจาก technology ที่เรียกว่า Builder(จะว่าอีกทีตอนหลังครับ) กับ การใช้ embed Ruby ซึ่งจะใช้การ embed Ruby ทั้งหมดในตัวอย่างที่จะทำให้ดู ซึ่งการใช้ .rhtml นี้แหละ จะเป็นการบอก Rails ว่า เราจะใช้ Embeded Ruby นะ(นี่เป็นอีกหนึ่งของ convention ใน Rails) ซึ่งถ้าจะใช้ Builder เราจะใช้เป็น .rxml แทน ต่อไปผมจะเรียก Embeded Ruby ว่า ERb นะครับ
ERb เป็นตัวที่ทำให้ .rhtml แปลงร่างกลายเป็น html หรือต่างๆ นานา ก็ได้ เช่น xml ตัว text ปกติ ก็จะเป็นปกติ แต่ถ้าหากเจอ <%=... %> เข้าไปละก็ มันจะทำการ execute ให้เป็น string มาดูตัวอย่างกันดีกว่า

<ul>
  <li>Addition: <%= 1+2 %></li>
  <li>Concatenation: <%= "Pun"+"Neng" %></li>
  <li>Time in one hour: <%= 1.hour.from_now %></li>
</ul>

พอเราไป view source ใน browser ดู มันจะเห็นเป็น html ดังนี้

<ul>
  <li>Addition: 3<li>
  <li>Concatenation: PunNeng</li>
  <li>Time in one hour: Tue Jun 13 22:00:00 SE Asia Standard Time 2006</li>
</ul>

แล้วในหน้า html ที่เราจะได้เห็นบน browser จะเป็นดังนี้

  • Addition: 3
  • Concatenation: PunNeng
  • Time in one hour: Tue Jun 13 22:00:00 SE Asia Standard Time 2006

แต่เรายังทำได้อีกอย่างหนึ่งใน rhtml คือ <%…%>(ไม่มี =) ถ้าเจออันนี้ละก็ มันจะทำการ execute ให้เหมือนกัน แต่มันจะไม่ออกมาเป็น output แต่จะใช้ช่วยในการจัดการกับ output มากกว่า มาดูตัวอย่างกัน

<% 3.times do %>
Ho!<br />
<% end %>
Merry Christmas!

พอกลับไปดูหน้า browser เราจะเห็นเป็น

Ho!
Ho!
Ho!
Merry Christmas!

หรือถ้าอยากจะใส่ loop โดยที่อยากให้ค่าในแต่ละ loop นั้น ไปมีเอี่ยวด้วย ก็ทำได้ เช่น

<% 3.downto(1) do |count|
<%= count %>...<br />
<% end %>
Lift off!

ใน browser จะเห็นเป็น

3...
2...
1...
Lift off!

หรือว่า เราอยากจะแสดงอักขระพิเศษ เช่น <…> หรือ & พวกนี้ ในความเป็นจริง เราอาจจะต้องใช้ html entities ในการแสดงผล อย่างที่ผมทำอยู่นี้ แต่ว่า Rails มีตัวช่วยครับ เราสามารถใช้ h() method ที่เป็น helper ช่วยได้ เช่น

Email: <%= h("Neng & PunNeng <pn@punneng.com>") %>

แล้วในหน้า browser เราก็จะเห็นว่า "Email: Neng & PunNeng pn@punneng.com" โดยที่อักขระต่างๆ จะแสดงได้โดยปกติ

Adding the Time

กลับมาที่ปัญหาเดิมของเรากันต่อ กับการที่จะใส่เวลาเข้าไปในหน้า app ของเรา คำถามแรกเรารู้แล้วว่าจะทำให้เป็น dynamic content ได้อย่างไร ต่อไป มาดูว่าจะเอาเวลามาจากไหนได้บ้าง หนึ่งอย่างที่ Ruby มีคือ Time.now() method มาลองดูกัน

<html>
<head>
  <title>Hello, Neng!</title>
</head>
<body>
  <h1>Hello Neng from Rails!</h1>
  <p>
    The time is <%= Time.now %>
  <p>
</body>
</html>

แบบนี้ ก็ทำงานได้เหมือนๆ กัน
ถ้าเราต้องการแค่นี้ แบบนี้ก็เพียงพอแล้ว แต่ในความเป็นจริง ถ้าเราต้องการทำอะไรที่มันต่างออกไปมากกว่านี้ หรือต้องการทำอะไรที่มันมากกว่านี้ เราสามารถทำได้โดยส่งค่าจาก controller มายังหน้านี้ได้ โดยเราอาจจะส่งผ่านมาทาง instance ได้ เช่นตัวอย่างต่อไปนี้ จะทำการส่งผ่านมาทาง instance ที่ชื่อว่า @time(เราตั้งเองได้นะครับ)

class SayController < ApplicationController
  def hello
    @time = Time.now
  end
end

แล้วในหน้า rhtml เราก็จะต้องแก้ไขเป็น

<html>
<head>
  <title>Hello, Neng!</title>
</head>
<body>
  <h1>Hello Neng from Rails!</h1>
  <p>
    The time is <%= @time %>
  </p>
</body>
</html>

ถ้า refresh แล้ว เราจะได้ดังตัวอย่างข้างล่าง

The Story So Far

มาดูกันดีกว่า ว่าที่ทำๆ มา มันมีความเป็นไปอย่างไรบ้าง

  1. user เข้ามากรอก URL ในที่นี้จะเป็น http://localhost:3000/say/hello
  2. Rails ทำการวิเคราะห์ URL แล้วทำการแยก controller ออกมา ในที่นี้จะเป็น say แล้วจึงทำการสร้าง instance ของ SayController (ที่เราทำไปใน app/controllers/say_controller.rb)
  3. ทำการแยก action ออกมา ในที่นี้จะเป็น hello แล้วจึงทำการเรียก method นี้ แล้วส่ง @time กลับมาให้
  4. Rails หา file ที่จะทำการแสดงค่าออกมา โดยหาจาก app/views แล้วหาข้างในด้วยชื่อที่เป็นชื่อของ controller ในที่นี้จะเป็น say ถ้าเจอแล้วจะเข้าไปหาข้างในอีก โดยใช้ชื่อของ action ซึ่งก็คือ hello (hello.rhtml)
  5. Rails ทำการ execute ERb ที่อยู่ใน rhtml
  6. ทำการแสดงผลออกทาง browser

อันนี้ยังไม่ใช่ process ทั้งหมด แต่เราก็ได้เห็นกระบวณการเบื้องต้นของ Rails กันแล้ว จะเห็นได้ว่า ผมได้บอกอยู่หลายๆ ที่เหมือนกัน ว่าตรงไหนที่เป็น convention หรือ ข้อกำหนดของ Rails เอาไว้ นี่จะเป็นตัวอย่างนึงที่แสดงให้เห็นถึง Convention over Configuration ของ Rails สังเกตได้ว่า เราไม่มีการ configure ต่างๆ เลย

Linking Pages Together

เว็บบ้าอะไรจะมีแค่หนึ่งหน้า ใช่ปะครับ งั้นเราก็ต้องเพิ่มหน้าสิ มาดูกัน เราจะทำต่อจากที่เราทำไว้นี่แหละ ต่อไปจะทำหน้า goodbye มันควรจะอยู่ใน controller ตัวไหน ??? จำเป็นไหม ที่จะต้องสร้าง controller ขึ้นมาใหม่ ?? ถามเองตอบเอง มันควรจะอยู่ใน say controller เราไม่จำเป็นต้องสร้างใหม่ ดูจากหน้าที่แล้ว เรา say hello แล้ว เราควรจะ say goodbye ใช่มะครับ :) มาใส่ code เลย ที่ say_controller.rb

class SayController < ApplicationController
  def hello
    @time = Time.now
  end
  def goodbye
  end
end

ต่อไปเราก็ทำการสร้าง goodbye.rhtml ใน app/views/say แล้วใส่ว่า

<html>
<head>
  <title>See You Later!</title>
</head>
<body>
  <h1>Goodbye!</h1>
  <p>
    It was nice having you here.
  </p>
</body>
</html>

แล้วลองเรียกผ่าน browser ด้วย http://localhost:3000/say/goodbye ดูว่าได้ตามนี้หรือเปล่า ok ละ ต่อไปเราจะทำให้สองหน้านี้ link กัน ซึ่งจริงๆ เราอาจจะใช้ button หรือแล้วแต่ความต้องการของผู้ใช้ละกัน แต่ในที่นี้ จะใช้ hyperlink ละกัน โดยที่เรารู้แล้วว่า convention ของ Rails มันจะส่งผ่านกันโดยใช้ controller กับ action ทางที่ง่ายที่สุด ที่จะทำการ link สองหน้านี้เข้าด้วยกันคือ ตามข้างล่างนี่เลย
ในหน้า hello.rhtml

<html>
  ...
  <p>
    Say <a href="/say/goodbye">GoodBye<a>!
  </p>
</html>

และในหน้า goodbye.rhtml

<html>
  ...
  <p>
    Say <a href="/say/hello">Hello<a>!
  </p>
</html>

link อันนี้ มันทำงานได้แน่นอน แต่ในอนาคตล่ะ มันอาจจะโดนย้ายไปอยู่ที่อื่นใน server ได้ หรือเราอาจจะต้องเปลี่ยน path ให้มันดีกว่านี้ เพราะฉะนั้น path มันจะเปลี่ยนไป วิธีแก้ง่ายๆ เลยคือการใช้ link_to() method ซึ่งจะทำหน้าที่สร้าง hyperlink ให้(จริงๆ มันทำได้มากกว่าสร้าง hyperlink นะครับ) เราก็เปลี่ยนที่หน้าของเราเลย เริ่มที่ hello.rhtml เลยละกัน เป็น

<html>
<head>
  <title>Hello, Neng!</title>
</head>
<body>
  <h1>Hello Neng from Rails!</h1>
  <p>
    The time is <%= @time %>
  </p>
  <p>
    Time to Say
    <%= link_to "GoodBye!", action => "goodbye" %>
  </p>
</body>
</html>

เราจะใช้ link_to ข้างใน <%=…%> มันจะทำการเปลี่ยนเป็น string ให้ โดยจะปรากฎออกมาเป็น hyperlink ส่วน parameter ตัวแรก ก็คือ ข้อความที่เราต้องการให้มันแสดงเป็น link ตัวถัดมา ก็จะเป็น action ซึ่งก็จะเป็น goodbye แต่ถ้ามีการโยงข้าม controller เราก็จะเพิ่ม parameter เข้าไปอีกตัว คือ controller เช่น controller => "other_controller" จากนั้น ทำเหมือนกันอีกทีในหน้า goodbye.rhtml โดยใน link_to เปลี่ยนเป็น link_to "Hello!", :action => "hello" ลองกลับไปดูที่ browser ดูว่าได้เหมือนกันหรือเปล่า คราวหน้าจะเป็น workshop แล้วนะครับ ขอเวลาเตรียมตัวทำซะหน่อย :)

ปล. เรื่อง syntax ของ Ruby ใจเย็นๆ นะครับ ค่อยๆ เรียนรู้กันไป เดี๋ยวผมจะเอาให้ให้ดูกันอีกที จะมาเจอกับมันเต็มๆ ใน part ของ Ruby ครับ ในส่วนของ Rails ก็เหมือนกัน อย่างคราวนี้ มี link_to() method ก็จะมี parameter อีกหลายตัว ไว้จะค่อยๆ นำมาเป็นตัวอย่าง ถ้าใครใจร้อน เข้าไปดูได้ที่ http://www.ruby-doc.org/core ในส่วนของ Ruby และ http://api.rubyonrails.org ในส่วนของ Rails

ปอ. ตอนนี้เรื่อง link ใน rails ค่อนข้างจะยืดหยุ่นมาก ไว้จะมาให้ดูอีกทีครับ

แก้ไขล่าสุด วันที่ 7 กรกฏาคม 2550 เวลา 0.30 น.

Filed Under: Ruby on Rails | Tags: howto ruby on rails

Comments

Have your say

A name is required. You may use HTML in your comments.




codegent: we're hiring