2011-09-11 12 views
0

私は、:email、:display_nameと:handleという3つのフィールドを持つUserモデルを持っています。ハンドルは:display_nameからシーンの背後に作成されます。Rails検証の問題

私は、次の検証を使用しています:

validates :display_name, :presence => :true, :uniqueness => { :message => "Sorry, another user has already chosen that name."}, :on => :update 
    validates :email, :presence => :true, :uniqueness => { :message => "An account with that email already exists." } 

私は、モデル内のto_paramとしてハンドルを使用します。ユーザーが既に存在する:display_nameを送信して検証に失敗した場合、それを変更してフォームを再送信しようとすると、Railsは新しいハンドルを電子メールの検証として使用するように見えます。つまり、電子メールは現在のユーザーに属していないため、電子メールの検証が失敗します。この時点で、Railsは、変更された表示名/ハンドルがルックアップに使用するものであるとみなし、新しいハンドルに基づいてユーザを見つけることができないため、更新アクションはまったく完了できません。

はここでupdateメソッドです:

def update 
    @user = User.find_by_handle(params[:id]) 
    @handle = params[:user][:display_name] 
    @user.handle = @handle.parameterize 
    ... 
end 

検証は最初の重複メールに失敗した場合、この問題は発生しませんので、私はそれが私がupdateメソッドを書いている方法についての何かだと仮定しています - - おそらく私はモデルのハンドルを設定しようとする必要がありますか?

答えて

2

多分私はモデルのハンドルを設定しようとする必要がありますか?

コントローラーはこのようなことを行う場所ではありません。その背後で起こっているモデルロジックで、ユーザーのコントロールを超えて、なぜコントローラコードに入れるのですか?

before_saveフィルタでは、選択した表示名が使用可能であると判断され、レコードが有効であると判断された場合にのみ実行されます。このようにして、handleは実際にdbにコミットされるまでキャッシュされたレコードで変更されず、誤って生成されたURLの問題が解消されます。

before_save :generate_handle 
... 

def generate_handle 
    self.handle = display_name.parameterize 
end 
+0

コントローラで設定していた理由を覚えていません。おそらく便宜です。 – Slick23