Modifying fieldWithErrors

Posted by PunNeng, Sat Jul 05 20:33:00 UTC 2008

fieldWithErrors เนี่ย บางทีมันก็มีประโยชน์ดีนะ แต่บางทีก็อยากจะเอาออก หรืออยากจะแก้ไข

เอาแบบนี้ดีกว่า

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|          
  if html_tag =~ /<label.*>.*<\/label>/
    "<div class=\"labelWithErrors\">#{html_tag}</div>" 
  elsif html_tag =~ /terms_and_conditions/   
    "<div class=\"tickWithErrors\">#{html_tag}</div>"
  elsif html_tag =~ /radio/
    "<div class=\"radioWithErrors\">#{html_tag}</div>"     
  else
    "<div class=\"fieldWithErrors\">#{html_tag}</div>"      
  end                            
end

ใส่ไปใน environment.rb
ใครมีความคิดอะไรก็ใส่ไปให้หมด สำหรับผมการ filter ง่ายๆ ก็ใช้ RegExp ครับ

ไม่มีกะจิตกะใจจะเขียนเท่าไหร่ กำลังทะเลาะกับ Merb อยู่ ทำไมมันติดตั้งยากเยี่ยงนี้ !!

0 comments | Filed Under: Ruby on Rails | Tags: activerecord fieldwitherrors howto ruby on rails

Ruby on Rails :: Customize Form helper

Posted by PunNeng, Sun Jun 29 03:00:00 UTC 2008

เพิ่งทำของเล่นเสร็จไปตัวนึง เลยไม่ได้เขียน blog

ไม่ต้องพล่ามมาก เอาเลยดีกว่า

ใน Rails มี Form helper อยู่ เราทำอะไรกับมันได้บ้าง?? ลองดูแบบนี้ก่อน

  1
  2
  3
  4
  5
  6
<% form_for :person, @person, :url => { :action => "update" } do |f| %>
  First name: <%= f.text_field :first_name %>
  Last name : <%= f.text_field :last_name %>
  Biography : <%= text_area :person, :biography %>
  Admin?    : <%= check_box_tag "person[admin]", @person.company.admin? %>
<% end %>

ปกติ ผมจะต้องใส่ label ให้มันด้วย
ผมไม่ค่อยชอบเลย ผมอยากได้

f.text_field :first_name

แล้วมันใส่ label ไปให้ผมเลย
มันทำได้โดยสร้าง module เพิ่ม ไปใว้ใน config/initializers/ (มันมาตอน rails 2.0 ออกมั้ง ทุก file ในนี้ จะถูกโหลดโดยอัติโนมัติ)

  1
  2
  3
  4
  5
  6
  7
module MyFormHelper
  class MyFormBuilder < ActionView::Helpers::FormBuilder
    def text_field(method, options = {})
      @template.content_tag('p', label(method) + <br /> + super)
    end
  end
end

ก็ extends ตามเรื่องไป(ต้องใช้พลังแงะนิดหน่อย)

ใน form ด้านบน ก็เพิ่ม :builder => MyFormHelper::MyFormBuilder
หน้าตาจะเป็นแบบนี้

  1
  2
  3
  4
  5
  6
<% form_for :person, @person, :url => { :action => "update" }, :builder => MyFormHelper::MyFormBuilder do |f| %>
  <%= f.text_field :first_name %>
  <%= f.text_field :last_name %>
  <%= text_area :person, :biography %>
  <%= check_box_tag "person[admin]", @person.company.admin? %>
<% end %>

แล้วผมก็จะได้ผลของการ render text_field เป็นแบบนี้

  1
  2
<p><label for="person_first_name">First name</label><br />
<input type="text" id="person_first_name" name="person[first_name]"</p>

อะไรประมาณนี้

0 comments | Filed Under: Ruby on Rails | Tags: form helper helper howto ruby on rails

RailsDB

Posted by PunNeng, Wed May 28 02:46:00 UTC 2008

ทุกชิ้นงาน(ของออฟฟิศ)ที่ผมทำบน rails อยู่ทุกวันนี้ host ด้วย vps ครับ แล้วตอนติดตั้ง ก็ขี้เกียจติดตั้งชุดแปล php ด้วย ผมเลยอยากได้อะไรเหมือน phpmyadmin ครับ
ทางเลือกแรก ต้องใช้ edge rails
มีตัวช่วยใหม่ ชื่อว่า dbconsole แต่ก็ยังเป็น command line แค่มัน remote ให้ แค่นั้นเอง
ทางเลือกที่สองก็คือ RailsDB
ทางเลือกที่สาม เอ่อ.. ช่วย comment บอกที

ย้อนกลับมาที่ RailsDB ครับ น่าจะใช้แทน phpmyadmin ได้มากที่สุด คืนนี้ ผมก็เลยลองซะ ผลที่ได้คือ error!!(เป็นปกติ)

มันพังเพราะ default config มันผิด ตอนต่อ db หน้าตาประมาณนี้

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
def switch_db( database )     
    case database.driver.name
      when 'sqlite3'
        ActiveRecord::Base.establish_connection(
          :adapter  => 'sqlite3',
          :database => database.path
        )
      when 'mysql'
        ActiveRecord::Base.establish_connection(
          :adapter  => 'mysql',
          :database => database.name,
          :host     => database.host,
          :username => database.username,
          :password => database.password
        )
      when 'postgresql'
        ActiveRecord::Base.establish_connection(
          :adapter  => 'postgresql',
          :database => database.name,
          :host     => database.host,
          :username => database.username,
          :password => database.password
        )
    end
  end

code ชุดนี้ อยู่ที่ app/models/switch.rb ครับ
สังเกตได้ว่า มันไม่มี port หรือ socket ให้กรอกครับ ค่า default ของ mysql ใน activerecord เองก็กำหนดไว้ว่า port เป็น 3306 และ socket เป็น /tmp/mysql.sock

วิธีซ่อมก็ง่ายๆ ครับ ใส่่ port หรือ socket ที่ถูกต้องเข้าไป

ประชาสัมพันธ์หน่อยครับ
มีงาน train (J)Ruby on Rails ของ narisa นะครับ ใครสนใจก็ตาม link ข้างล่างเลย
วันจัด train เรื่อง (J)Ruby On Rails ครับ - Narisa.com

2 comments | Filed Under: Ruby on Rails | Tags: activerecord database phpmyadmin railsdb ruby on rails

Better error messages for validation

Posted by PunNeng, Sat Apr 26 02:38:00 UTC 2008

แว่บๆ ไปอ่าน feed เจอของ Softies on Rails
error_messages_for เปลี่ยนไป(ตอนไหนไม่รู้)
ที่เคยเขียนไปของเก่า จำได้ว่ามันแก้ header_messages ไม่ได้ เลยต้องแก้เอง เพราะหน้าตาใน helper ของเก่าเป็นแบบนี้

  1
header_message = "#{pluralize(count, 'error')} prohibited this #{(options[:object_name] || params.first).to_s.gsub('_', ' ')} from being saved"

แว่บไปดูใน API ไปเจอว่าเปลี่ยนไปจริงๆ ได้ของแถมมาอีก คือ error_messages_on ซึ่งผมไม่เคยใช้มาก่อน(บ้านนอก)

list ข้างล่างคือค่า params ที่เราจะใส่ไปได้ใน error_messages_for

  • header_tag ค่า default เป็น h2
  • id ค่า default เป็น errorExplanation
  • class ค่า default เป็น errorExplanation
  • object ไว้เซ็ตค่ากรณีที่ไม่มี object ที่ต้องใส่ตาม convention เช่น

error_messages_for 'user'

ถ้าจะให้ขึ้น ฝั่ง view จะต้องมองเห็น @user แล้ว error ถึงจะออก
แต่แบบใหม่นี่ สามารถอ้างได้จาก object อื่นได้เลย เช่น

error_messages_for 'user', @question.user

  • object_name ตรงตัว ถ้าไม่ใส่ จะไปใช้ object แทน ในตัวอย่างคือ User
  • header_message ตรงตัว ค่า default เป็น X errors prohibited this object from being saved ซึ่ง X ก็คือ object_name นั่นแหละ
  • message คือข้อความที่อยู่ใต้ header_message และมาก่อน error list ค่า default เป็น There were problems with the following fields:

ถัดมาก็ error_message_on
ไม่มีอะไรง่ายกว่าการดูตัวอย่าง

  1
  2
  3
  4
  5
  6
  7
  8
<%= error_message_on "post", "title" %> =>
<div class="formError">can't be empty</div>

<%= error_message_on @post, "title" %> =>
<div class="formError">can't be empty</div>

<%= error_message_on "post", "title", "Title simply ", " (or it won't work).", "inputError" %> =>
<div class="inputError">Title simply can't be empty (or it won't work).</div>

ปล. นึกไม่ออกว่าข้อความไหน อยู่ตรงไหน ย้อนกลับไปดของเก่าได้ครับ

0 comments | Filed Under: Ruby on Rails | Tags: activerecord ruby on rails validation

BDD guide #1 When do I mock?

Posted by PunNeng, Sun Mar 09 21:52:00 UTC 2008

ผมเคยสับสนมานานว่าเมื่อไหร่ควรจะ mock และคนที่เคลียร์ปัญหาคาใจผมก็คือเจ้านายผมเอง
เขาบอกโดยสรุปว่า

mock ในส่วนที่เราไม่พิจารณา

เช่นใน controller เราจะพิจารณาที่ logic ของ controller เท่านั้น ในส่วนของ model ที่เราเรียกใช้งานก็ไม่ต้องสนว่าจริงๆ แล้วมันทำงานยังไง เราเลย mock ที่ model ไปเลย ส่วนจะ lock การคืนค่าหรือตัวแปรต่างๆ ก็ stub เอา ส่วน logic ต่างๆ ก็
กระโดนมาส่วน model บ้าง ในส่วนของ model ที่เรา mock ใน controller ไปแล้ว เราควรจะมา test อีกที ทีนี้เราพิจารณา logic ใน model ซึ่งโดยมากแล้วก็ไม่รู้จะ mock อะไร เพราะมันล้วนซึ่งต้องทำงานตาม code ที่เขียนไว้จริงๆ(ดูคล้ายๆ กับ unit test)

มาดูตัวอย่างกัน
ตัวอย่าง 1
อันนี้เป็นตัวอย่างจาก scaffold
สิ่งที่ mock ล้วนซึ่งเป็น model ทั้งนั้น เริ่มจาก before ด้วยการ mock ไปก่อนแล้วตามด้วย stub
ที่ต้อง stub เพราะต้องจำลองผล เพราะเรา mock model มาอีกทีนึง มันจึงไม่แตะ code ของ model จริงๆ
ยังมีส่วนของการ render/redirect ใน controller อีก แต่อันนี้ เราจำเป็นต้องวัดผล(พิจารณา)มันจริงๆ เลยไม่จำเป็นต้อง mock ในส่วนของ render/redirect

ตัวอย่าง 2 จากLuke Redpath

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
describe "A user (in general)" do
  setup do
    @user = User.new
  end

  it "should be invalid without a username" do
    @user.email = 'joe@bloggs.com'
    @user.should_not_be_valid
    @user.errors.on(:username).should_equal "is required" 
    @user.username = 'someusername'
    @user.should_be_valid
  end

  it "should be invalid without an email" do
    @user.username = 'joebloggs'
    @user.should_not_be_valid
    @user.errors.on(:email).should_equal "is required" 
    @user.email = 'joe@bloggs.com'
    @user.should_be_valid
  end
end

ตัวอย่างนี้ไม่มี mock สักตัว เพราะต้องการ test logic ที่มันควรจะเป็นจริงๆ

แต่ถ้า model มีการทำงานร่วมกับ model ตัวอื่น อันนี้ก็น่าจะ mock เป็นต้น

0 comments | Filed Under: Ruby on Rails | Tags: behavior driven development mock rspec ruby on rails

codegent: we're hiring