9/11/2006

validates_associated 的用法

如果當你在一個 Form 裡面使用兩個以上的 Model
而且你又想要 跨 Model Validate
那你就得使用 validates_associated

舉個例子
兩個 Model : user , : user_data
user 裡面有 name , email 需要 validate
user_data 裡面有 sex 需要 validate
並且我們將 view 加入 error_message_of
# Model
class User < ActiveRecord::Base
has_one :user_data
validates_presence_of :name , :email
validates_associated :user_data
end

class UserData < ActiveRecord::Base
belongs_to :user
validates_presence_of :sex
end

#View
<%= error_validate_of 'user' %>

如此當我們這些欄位有 insert 過不了 validate
他就會顯示跨 Model 的 error message

但是這裡有一個問題

如果這個例子中的 sex 出現 validate error
我們會發現到他僅僅顯示

There were problems with the following fields:

  • User data is invalid
  • Email can't be blank
只會顯示 Model Name is invalid
並非是原先我們預計的 sex can't be blank
代表雖然他會去 involke associated model 的 validate function
但是顯示還不夠

如果加上
<%= error_messages_for 'user_data' %>
那就會顯示 Sex can't be blank

There were problems with the following fields:
  • User data is invalid
  • Email can't be blank

There were problems with the following fields:

  • Sex can't be blank

問題又來了
我們不需要兩個 error message 呀~~~
而且 User data 跟 sex 其實是重複的 message

難道這兩個真的難兩全?

解決方式

其實解決方式很簡單,我們捨棄 error_message_of 的作法
採用國內常使用的error message 跟在 form input field 後面的作法
那麼就很簡單啦

model validate 如果出現 error
Rails 在 Model Variable 當中會增加一個 errors hash
如果今天 User 裡面的 email 欄位有 validate error
而我們又用 @user 來代表這個 Model variable
@user.errors['email'] 就會有值,而那個值就是 validate_...._of 裡面的 message 變數
(像上面的例子用 error_message_for,他會出現 Email can't be blank
@user.errors['email'] 就是 'can't be blank' )

那麼我們可以這樣寫
<p><label for="user_email">Emaillabel><br/>
<%= text_field 'user', 'email' %><%= @user.errors['email'] %>p>

<p><label for="user_email">Sexlabel><br/>
<%= text_field 'user_data', 'sex' %>
<%=
@user.user_data.errors['sex'] if @user.user_data %>p>
我們發現 error message 就會跟在錯誤的欄位旁邊
更棒的是,錯誤會將欄位包起來的紅色框框依舊存在

更好用的是,這個方式他不會 show 出 database 的 column 英文名字
只會 show 出 message 變數
所以我們可以更大膽的使用
  validates_presence_of :sex , :message => '請加入性別'
如此就會出現


擷圖_1


Viva ,我們解決了這個問題,還能順便中文化耶~~~

ps.

errors message 也可以這樣玩

1 則留言:

Suave 提到...

very useful~I'm a rails newbie