ผลต่างระหว่างรุ่นของ "418342 ภาคปลาย 2552/ปฏิบัติการที่ 8"
Cardcaptor (คุย | มีส่วนร่วม) |
Cardcaptor (คุย | มีส่วนร่วม) |
||
แถว 54: | แถว 54: | ||
== แก้ไขโมเดล == | == แก้ไขโมเดล == | ||
− | ในฟอร์มข้างบน เราสั่ง <tt>f.file_field :photo</tt> เหมือนกับว่า photo เป็นฟีลด์หนึ่งของโมเดล person แต่ความจริงแล้ว person ไม่ได้มีฟีลดิ์นี้แต่อย่างใด อย่างไรก็ดี เราสามารถสร้าง "ฟีลด์เทียม" ชื่อ photo | + | ในฟอร์มข้างบน เราสั่ง <tt>f.file_field :photo</tt> เหมือนกับว่า photo เป็นฟีลด์หนึ่งของโมเดล person แต่ความจริงแล้ว person ไม่ได้มีฟีลดิ์นี้แต่อย่างใด อย่างไรก็ดี เราสามารถสร้าง "ฟีลด์เทียม" ชื่อ photo ได้ด้วยการเพิ่มเมธอด <tt>photo=</tt> เข้าในโมเดล Person |
<geshi lang="ruby"> | <geshi lang="ruby"> | ||
+ | class Person < ActiveRecord::Base | ||
def photo=(file_data) | def photo=(file_data) | ||
unless file_data.blank? | unless file_data.blank? | ||
แถว 62: | แถว 63: | ||
end | end | ||
end | end | ||
+ | end | ||
</geshi> | </geshi> |
รุ่นแก้ไขเมื่อ 02:27, 15 มกราคม 2553
ในปฏิบัติการที่ 8 นี้เราจะทำการสร้าง web application ที่เก็บข้อมูลของบุคคลพร้อมทั้งรูปภาพของคนคนนั้น
เนื้อหา
การเก็บไฟล์ของเวบแอพพลิเคชัน
ไฟล์รูปภาพหรือไฟล์อื่นๆ ที่ web application จัดเก็บมักเป็นไฟล์ขนาดใหญ่ จึงไม่เหมาะสมที่จะเก็บมันไว้ในฐานข้อมูลโดยตรง (แต่ไม่ได้หมายความว่าเราจะเก็บมันด้วยฐานข้อมูลไม่ได้) ในกรณีของ web application ของเรา เราจะเก็บไฟล์รูปภาพไว้ในไดเรกทอรี RAILS_ROOT/public/photo_store โดยที่ RAILS_ROOT คือไดเรกทอรีของ web application ที่เราสร้างด้วยคำสั่ง rails
สิ่งที่เราจะต้องคำนึงถึงต่อไปคือเราจะตั้งชื่อไฟล์รูปภาพเหล่านั้นว่าอย่างไร เราไม่สามารถใช้ชื่อไฟล์ที่ผู้ใช้ส่งมาได้โดยตรง เพราะชื่อไฟล์ของผู้ใช้หลายๆ คนอาจซ้ำกันได้ เพื่อหลีกเลี่ยงปัญหานี้ เราจะตั้งชื่อไฟล์ตาม primary key ของตารางบุคคลที่เราเก็บ เช่น ไฟล์รูปภาพของคนที่มี primary key เท่ากับ 10 ก็จะมีชื่อไฟล์ว่า "10" (ยังไม่รวม extension) เป็นต้น
ไฟล์รูปภาพที่ผู้ใช้ส่งมาไม่ได้หลายรูปแบบ เช่น JPEG, GIF, หรือ BMP เป็นต้น และเราควรจะสามารถจัดการกับรูปภาพได้ทุกแบบ กล่าวคือ ถ้าผู้ใช้ส่งภาพแบบ JPEG ให้เป็นภาพของคนที่มี primary key เท่ากับ 25 เราควรจะตั้งชื่อไฟล์ของคนคนนั้นว่า "25.jpg" แต่ถ้าไฟล์มีรูปแบบ PNG เราก็ควรจะตั้งชื่อว่า "25.png" เป็นต้น ฉะนั้น เพื่อให้เรารู้ว่าไฟล์รูปภาพมีรูปแบบอะไร เราจะต้องเก็บ extension ของไฟล์รูปภาพไว้ในโมเดลของบุคคล
สร้าง web application และโมเดล
เราเริ่มต้นจากการสร้าง application ชื่อ people
rails people cd people
แล้วเราจะทำการสร้าง model ชื่อ person สำหรับเก็บบุคคล เพื่อความง่าย person จะมีฟีลด์เพียงแค่ 2 ฟีลด์ คือ ชื่อ และ extension ของรูปที่ผู้ใช้ upload
ruby script/generate scaffold person name:string extension:string
หลังจากนั้นเราสั่ง
rake db:migrate
เพื่อสร้างฐานข้อมูล
เปลี่ยน form เพื่อ upload รูป
เราจะต้องทำการเปลี่ยน app/views/people/new.html.erb เพื่อให้ผู้ใช้สามารถอัพโหลดรูปได้
อันดับแรกให้เราทำการลบโค้ด <geshi lang="html">
<%= f.label :extension %>
<%= f.text_field :extension %>
</geshi> ออกก่อน เนื่องจากเราไม่ต้องการให้ผู้ใช้ป้อน extension ของไฟล์ด้วยตนเอง
ให้เราเพิ่มโค้ด <geshi lang="html">
Photo
<%= f.file_field :photo %>
</geshi> เข้าไปแทนที่โค้ดส่วนที่เราลบออกไป
และให้ไปแก้ไขบรรทัด <geshi lang="html"> <% form_for(@person) do |f| %> </geshi> ให้เป็น <geshi lang="html"> <% form_for(@person, :html => { :multipart => true } ) do |f| %> </geshi> ส่วน :html => { :multipart => true } นี้จะทำการเปลี่ยน tag form ใน HTML จาก
<form action="/people" method="post">
ให้กลายเป็น
<form action="/people" enctype="multipart/form-data" method="post">
คุณสมบัติ enctype="multipart/form-data" เป็นตัวบอกให้ browser ส่งข้อมูลมาหลายๆ ส่วน กล่าวคือ web browser จะมีการส่งข้อมูลรูปไปยัง web server ทีหลังข้อมูลอื่นๆ ของฟอร์ม ในทางกลับกัน web server ก็จะทราบว่าตัวเองจะต้องรับข้อมูลรูปซึ่งจะตามมาทีหลังด้วย
แก้ไขโมเดล
ในฟอร์มข้างบน เราสั่ง f.file_field :photo เหมือนกับว่า photo เป็นฟีลด์หนึ่งของโมเดล person แต่ความจริงแล้ว person ไม่ได้มีฟีลดิ์นี้แต่อย่างใด อย่างไรก็ดี เราสามารถสร้าง "ฟีลด์เทียม" ชื่อ photo ได้ด้วยการเพิ่มเมธอด photo= เข้าในโมเดล Person <geshi lang="ruby"> class Person < ActiveRecord::Base
def photo=(file_data) unless file_data.blank? @file_data = file_data self.extension = file_data.original_filename.split('.').last.downcase end end
end </geshi>