Ruby on Rails :: ว่าด้วยเรื่องของ Encoding
Posted by PunNeng, Wed Jul 19 15:40:00 UTC 2006
AMp เขียนครับ
แนะนำตัวกันก่อน ผม AMp นะครับ ใครที่เล่น TFD (ThaiFlashDev) น่าจะรู้จักกันดี ตอนนี้ย้ายก้นจาก Flash กะ php มาเล่น Ruby มั่งละ
เอาล่ะ เข้าเรื่องกันเลยดีกว่า
หลังจากผมเล่น Ruby มาได้ 2 วัน ก็รู้สึกว่า Ruby on Rails ถึงแม้ว่ามันจะฉลาดขนาดไหน ก็ยังคงมีปัญหาเรื่อง Encoding มาให้ปวดหัวอีกจนได้ นั่นก็คือ ใช้ภาษาไทยไม่ได้!!! ทั้งเรื่องการแสดงผล และการเก็บข้อมูลลงฐานข้อมูล ซึ่งในเรื่องฐานข้อมูลนี้ผมจะอ้างอิงแค่ MySQL อย่างเดียวนะครับ ฐานข้อมูลอื่น ไม่ทราบว่าจะมีปัญหาด้วยหรือเปล่านะ
เรามาไล่แก้ปัญหาเรื่อง Encoding ใน Ruby ทีละจุดเลยดีกว่า
Source File Encoding
จุดแรก อยู่ใน RadRails ครับ
RadRails เป็น IDE ตัวเดียวของ Ruby ที่ผมรู้จัก (แล้วจะบอกทำไมเนี่ย - -') ฉะนั้น ใครที่ไม่ได้ใช้ RadRails ก็ข้ามจุดนี้ไปได้เลยครับ
--ภ--ายหลังจากที่เราสร้างโปรเจกของ RoR ใน RadRails ขึ้นมาแล้ว ปกติไฟล์ต่างๆ ที่ถูกสร้างขึ้นมาโดย RadRails นั้น จะถูกกำหนด encoding เป็น MS874 ซึ่งเป็น encoding ที่ระบบไม่รู้จัก และการที่ไฟล์ต่างๆ ถูกกำหนด encoding ให้เป็น MS874 นั้น จะทำให้เราไม่สามารถพิมพ์อะไรเพิ่มลงไปใน editor ได้เลย เพราะถ้าพิมพ์ไปแล้ว กดเซฟ โปรแกรมมันจะบอกว่า encoding ไม่ support
วิธีแก้คือ ให้คลิกขวาที่ Project ของเรา ที่อยู่ใน Rails Navigator ทางซ้ายมือของจอ แล้วเลือก Properties หลังจากนั้น ตรง text file encoding ให้ใส่เป็น TIS-620 เลยครับ (ใน list ไม่มีให้เลือก) เสร็จแ้ล้วกด apply ครับ และด้วยวิธีการนี้ เราก็สามารถใช้งาน IDE ได้ตามปกติแล้ว ทั้งเรื่องการแสดงภาษาไทยใน IDE แล้วก็การพิมพ์--ภ--าษาไทยด้วย (เอ้อ รวมไปถึงเรื่องการทำงานกับภาษาไทยใน ruby ได้ถูกต้องด้วยนะครับ)
Data Package Encoding
จุดที่สอง อยู่ในข้อมูลที่ Ruby ได้ reponse ออกมาให้ Browser หรือพูดให้เข้าใจง่ายๆ คือ Character Set นั่นเอง ซึ่งตามปกติแล้ว ruby จะใช้เป็น UTF-8 วิธีแก้คือ ให้ Ruby สร้าง header ขึ้นมาบอกว่า ข้อมูลที่ Ruby ได้ response ออกไปนั้น ใช้ character set อะไร โดยสั่ง
@headers["Content-Type"] = "text/html; charset=TIS620" |
ซึ่ง character set ที่กำหนดนี้ ไม่ใช่เป็นการกำหนดโดยใช้วิธีสร้าง meta tag นะครับ แต่เป็นการกำหนดที่ header ของการสื่อสารในโปรโตคอล tcp/ip เลย ฉะนั้นทำให้เรามั่นใจได้ว่า ระหว่าง client กับ server จะรับส่งข้อมูลเป็น TIS-620 เสมอ
คำสั่งกำหนด character set ใน header นั้น ถ้าจะให้ถูก ควรนำไปใส่ไว้ใน controller แต่ละตัว(ทุกๆ ตัว) เช่น สมมุติว่าผมมี controller ที่ชื่อ Category ก็จะต้องใส่โค้ดดังนี้
1 2 3 4 5 6 7 | class CategoryController < ApplicationController before_filter :configure_charsets def configure_charsets @headers["Content-Type"] = "text/html; charset=TIS620" end end |
และหลังจากนั้น เราก็ต้องไม่ลืมสร้าง meta tag สำหรับกำหนด character set ด้วย ซึ่งแท็กตัวนี้ ก็เป็น meta tag ใน html นั่นแหละครับ ไม่ใช่คำสั่งของ ruby แต่อย่างใด ฉะนั้น ให้เอาแท็กตัวนี้ไปใส่ไว้ในไฟล์ rhtml ทุกไฟล์เลยครับ
<meta content="text/html; charset=utf-8" http-equiv="content-type" />
|
เมื่อทำทั้งสองขั้นตอนครบแล้ว ตอนนี้หน้าเว็บที่ ruby สร้างขึ้นมา ก็จะมี encoding แบบ TIS-620 เรียบร้อยแล้ว ทำให้สามารถแสดงผลภาษาไทยได้อย่างถูกต้อง และข้อมูลที่ส่งจากฟอร์มใน browser มายัง ruby ก็จะมี encoding เป็น TIS-620 ด้วยเหมือนกันครับ
MySQL Communication Encoding
มาถึงจุดที่ 3 ที่เราต้องแก้ นั่นก็คือ MySQL
จริงๆ แล้วปัญหาตรงนี้ ผมว่าทุก--ภ--าษาที่ติดต่อ mysql ก็น่าจะเจอเหมือนกัน เพราะตอนที่ผมใช้ php ก็เป็น คือเวลา insert ข้อมูลที่เป็นภาษาไทยเข้าไปใน mysql แล้วจะได้เป็นตัว ???? ซึ่งมันอ่านไม่รู้เรื่อง ฉะนั้น วิธีแก้ก็จะเหมือนๆ กัน นั่นก็คือการใช้ sql command สั่ง mysql ว่าเราจะใช้ encoding เป็น TIS-620 นะ
SET NAMES TIS620 |
อันนี้คือคำสั่งพื้นฐาน แต่ถ้าเราจะเอามาใช้ใน Ruby ก็ให้แทรกโค้ดเพิ่มเข้าไปในวิธีที่แล้ว ก็จะได้โค้ดเป็น
1 2 3 4 5 6 7 8 9 10 11 12 | class CategoryController < ApplicationController before_filter :configure_charsets def configure_charsets @headers["Content-Type"] = "text/html; charset=TIS620" suppress(ActiveRecord::StatementInvalid) do ActiveRecord::Base.connection.execute 'SET NAMES TIS620' end end end |
จากโค้ดด้านบนนี้ ทำให้ ทุกๆ ครั้งที่มีการเรียก controller นี้ จะมีการ set header ให้บอกว่าข้อมูลจะมี character set เป็น TIS-620 และบอก mysql ว่าจะใช้ TIS-620 ด้วยเช่นกัน แต่ถ้าใน controller ไหนไม่มีการเชื่อมต่อ mysql ก็ไม่ต้องใส่โค้ดที่เอาไว้บอก mysql ถึง encoding ที่เราจะใช้นะครับ (มันจะกลายเป็น overhead ของระบบซะปล่าวๆ)
ถ้าหากใครอ่านแล้วงง มีคำถามอยากจะถาม โพสถามได้เลยนะครับ แล้วรออีเหน่งมาตอบละกัน อิอิ
Reference http://wiki.rubyonrails.org/rails/pages/HowToUseUnicodeStrings
แก้ไขล่าสุด วันที่ 8 กรกฏาคม 2550 เวลา 00.24 น.
