2012-05-01 11 views
3

validates_uniqueness_of:some_field属性が変更されていなくても(他のフィールドが変更された場合でも)some_fieldは「保存」で実行されるようです。各validates_uniqueness_ofはデータベース呼び出しを必要とするため、これは無駄に思えます。私は、some_fieldが変更されたかどうかを確認するためにProcをvalidates_uniqueness_ofに渡すことができることを知っています。そして、可能な限り、すべてのバリデーションを検討しています。私が疑問に思うのは:Railsは変更されていない属性を検証するのはなぜですか?

1)パフォーマンスに関心のある人は、一般的にその検証に関して何をしていますか?

2)属性が最初に変更されたかどうかを確認するために、validates_uniqueness_ofのデフォルト動作ではないのはなぜですか?

3)変更されていない属性に対してこのような検証を実行する理由はありますか?

私はRails 2.3を使用しています(現時点では、アップグレードを進めています)。私はこれがRails 3の同じ状況だとは知らない。

+0

2と3については、Railsアプリケーションの外部で値をデータベースに入れることができます。したがって、別のアプリによって追加された値によって、変更されていない属性が無効になる可能性があります。さらに、検証は時間とともに進化し、変更されていない属性を無効にすることができます。 – niiru

+0

@niiru:お返事いただきありがとうございます。ユーザーの観点から見ると、レコードの一部を編集して、レコードの別の部分が無効であり、編集されておらず、変更から論理的に独立していると伝えられます。また、あなたのシナリオで、レールアプリがフィールド上で一意性を強制している場合、他のアプリケーションも同じことをしてはいけませんか? –

+0

間違いなく!しかし、いくつかのアプリケーションに縛られているデータベースで作業している可能性があります。そのすべてがアプリケーションのデータ検証に責任があるわけではありません。 – niiru

答えて

2

誰かがデータベースの値を直接変更したらどうなるだろうか?

他の(非レールアプリ)アプリもデータベースにアクセスするとどうなりますか?

上記のすべてのシナリオでは、あなたのデータが有効で、レールアプリケーションが期待どおりに動作するようにしたいと考えています。データが改ざんされた場合(他のアプリやデータベースで直接)、データが必要ないため、あなたのレールアプリはエラーを投げます。

これは既定の動作です。デフォルトの動作は、データの有効性を維持し、エラー、省略、および時折の間違いの範囲を最小限に抑えるために、一般的により限定的です。あなたのケースでのパフォーマンスが心配な場合は、オブジェクトが頻繁に更新されていて、それが頻繁に更新されていないフィールドで長いカスタム検証があり、その検証をそれぞれ実行したくない場合あなたが質問で説明したように、デフォルトの動作をカスタマイズすることは理にかなっています。

0

私はこの同じ問題をRails 3.0アプリケーションで実行しました。私は、ユニークな属性がユーザーによって編集されたかどうかを調べることによって解決しました。以下は、私のUserオブジェクトのコード例です。

class User < ActiveRecord::Base 

attr_accessible :email, :password, :ha1, :ha1b, :sip_username, :domain 

validates :sip_username, :presence => true, :uniqueness => true, 
         :unless => :update_username?, 
         :exclusion => {:in => %w(9196), 
         :message => "9196 is reserved, please choose another"} 
def update_username? 
    # check to see if we are updating a sip_username for an existing user 
    stored_user = User.find_by_sip_username self.sip_username 
    # the id of the user is the same as me and sip_username hasn't been changed. skip validations. 
    if (stored_user.present?) 
    stored_user.id == self.id && stored_user.sip_username == self.sip_username 
    end 
end 
関連する問題