Tik’s Blog

ร้อยแปดพันเก้า

แก้ unit test failure ใน RailsSpace หลังอัพเกรดเป็น Rails 2.3

with one comment

โพสก่อนหน้านี้จบด้วยการเจ๊งของ unit test และก็ไปอาบน้ำนอน

วันนี้เลยลองหาต้นเหตุดูว่าปัญหาเกิดจากอะไร ได้ความว่าต้นเหตุของปัญหาเกิดจาก 2 method ใน user_controller_test เท่านั้นเอง คือ cookie_expires กับ cookie_value

ปัญหาแรกคือ

1) Error:
test_login_success_with_remember_me(UserControllerTest):
NoMethodError: undefined method `expires' for "1":String
/test/functional/user_controller_test.rb:268:in `cookie_expires'
/test/functional/user_controller_test.rb:145:in
`test_login_success_with_remember_me'

ซึ่งเกิดเพราะว่าใน Rails 2.3 นั้นการเรียกใช้ cookies[symbol.to_s] จะไม่คืน cookie object แล้วแต่ว่าคืนค่าของคุ๊กกี้นั้นๆเลย (ลองดู API)  ทำให้เราไม่สามารถใช้ expires ได้แล้ว

ที่ทำให้ซับซ้อนยิ่งกว่านั้น (และยังหาทางลัดใน Rails ไม่เจอ) คือเราเข้าถึงคุ๊กกี้ผ่าน @response.headers["Set-Cookie"] ได้เท่านั้น และค่าที่คืนมาจาก header นี้เป็น array ของ string ที่แต่ละ element แทนคุ๊กกี้หนึ่งอัน  เช่น

(rdb:1) @response.headers["Set-Cookie"]
["remember_me=1; path=/; expires=Wed, 19-Mar-2014 16:29:09 GMT", "authorization_token=56d1799d501a6ea5f0e612d22ddba211dc4066ae; path=/; expires=Wed, 19-Mar-2014 16:29:09 GMT"]

ในกรณีนี้สิ่งที่เราต้องการ (expires) อยู่ที่ element แรกของ array  ซึ่งเราสามารถแก้โค้ดเป็นแบบนี้ได้

def cookie_expires(symbol)
Time.zone.parse(@response.headers["Set-Cookie"][0].split("\;")[2].split("=")[1])
end

ไม่ได้เขียนให้อ่านง่ายมากนัก และก็ไม่ค่อยยืดหยุ่นด้วย แต่ดูเหมือนจะใช้งานได้  สิ่งที่เราทำก็คือเอา item แรกของ array ซึ่งตรงกับคุ๊กกี้ที่เราต้องการ (remember_me) มาแบ่ง string ด้วยเครื่องหมาย semicolon ก่อน แล้วก็เอา item สุดท้ายจากที่แบ่งได้ (expires) มาแบ่งด้วยเครื่องหมายเท่ากับอีกทีเพื่อเอาค่าของ expires มาแปลงเป็นเวลาเพื่อเปรียบเทียบ

แน่นอนว่าอ๊อบเจ็คต์ที่เราคืนกลับไปอาจไม่ใช่เวลาที่ตรงกับเวลาของคุ๊กกี้ที่เราเซ็ตค่าไว้ผ่านคอนโทรลเลอร์ แต่ว่าก็ยังอยู่ใน range การเปรียบเทียบของ test ได้ ซึ่งเพียงพอจะทำให้ผ่านการทดสอบ

อีกปัญหานึงที่เกิดกับ cookie_value ก็ด้วยเหตุผลเดียวกันกับที่เขียนไว้ด้านบน คือการ access hash คุ๊กกี้นั้นจะคืนค่าของคุ๊กกี้เลย ไม่ได้คืน array อีกต่อไป ทำให้เราต้องแก้เป็น

def cookie_value(symbol)
cookies[symbol.to_s]
end

หลังจากแก้ไขเรียบร้อยก็ test อีกทีเพื่อความแน่ใจ

ปล. เดาว่าการที่เราต้องเข้าถึงคุ๊กกี้ผ่าน “Set-Cookie” น่าจะเป็นผลจากการที่ Rails 2.3 เปลี่ยนมาสนับสนุน Rack เต็มรูปแบบแล้วในแบบของ middleware จึงทำให้โครงสร้างของเฟรมเวิร์คเปลี่ยนไปเก็บคุ๊กกี้ที่ HTTP request/response แทน

Written by sukita

มีนาคม 19, 2009 ที่ 11:46 pm

บันทึกโพสใน Programming

Tagged with

มีการตอบกลับหนึ่งครั้ง

Subscribe to comments with RSS.

  1. ยกโทษของฉันไวยากรณ์ (ฉันใช้ http://translate.google.com จากภาษาอังกฤษเป็นภาษาไทย), เพียงแต่ฉันต้องการกล่าวขอบคุณสำหรับการโพสต์นี้. การมหัศจรรย์ของเว็บไซต์ของ Google แปลผมสามารถรวบรวมเพียงพอจากบทความของคุณเพื่อแก้ปัญหาเดียวกันแน่นอนฉันคือมีกับ RailsSpace และทางรถไฟ 2.3.2. ขอขอบคุณอีกครั้ง!

    Happy reader

    เมษายน 5, 2009 at 6:58 am


ใส่ความเห็น