20

与えられたモデル

class BaseModel < ActiveRecord::Base
  validates_presence_of :parent_id
  before_save :frobnicate_widgets
end

派生モデル(基礎となるデータベーステーブルにはtypeフィールドがあります-これは単純なrails STIです)

class DerivedModel < BaseModel
end

DerivedModel良いOOの方法でBaseModel、を含むすべての動作をから継承しvalidates_presence_of :parent_idます。の検証をオフにしDerivedModel、コールバックメソッドが起動しないようにします。できれば、変更したり、壊したりすることはありません。BaseModel

これを行うための最も簡単で堅牢な方法は何ですか?

4

7 に答える 7

46

次のパターンを使用するのが好きです。

class Parent < ActiveRecord::Base
  validate_uniqueness_of :column_name, :if => :validate_uniqueness_of_column_name?
  def validate_uniqueness_of_column_name?
    true
  end
end

class Child < Parent
  def validate_uniqueness_of_column_name?
    false
  end
end

Rails がこれを回避するための skip_validation メソッドを提供していればよいのですが、このパターンは機能し、複雑な相互作用を適切に処理します。

于 2009-03-28T08:27:11.643 に答える
9

@Jacob Rothsteinによる回答のバリエーションとして、親でメソッドを作成できます。

class Parent < ActiveRecord::Base
  validate_uniqueness_of :column_name, :unless => :child?
  def child?
    is_a? Child
  end
end

class Child < Parent
end

このアプローチの利点は、Childクラスで検証を無効にする必要がある列名ごとに複数のメソッドを作成する必要がないことです。

于 2012-04-18T11:06:20.417 に答える
3

ソースを調べてみると (私は現在 Rails 1.2.6 を使用しています)、コールバックは比較的単純です。

before_validation_on_createなどのメソッドは、引数を指定してbefore_save呼び出されない場合、その「コールバック サイト」に割り当てられている現在のすべてのコールバックを保持する配列を返します。

before_save のものをクリアするには、次のようにします。

before_save.clear

そしてそれはうまくいくようです

于 2008-11-10T23:45:46.630 に答える
2

よりクリーンな方法は次のとおりです。

class Parent < ActiveRecord::Base
  validate :column_name, uniqueness: true, if: 'self.class == Parent'
end


class Child < Parent
end

または、次の方法でも使用できます。

class Parent < ActiveRecord::Base
  validate :column_name, uniqueness: true, if: :check_base

  private

  def check_base
    self.class == Parent
  end
end


class Child < Parent
end

したがって、モデルのインスタンス クラスが の場合、一意性の検証が行われますParent

  1. のインスタンス クラスは でChild ありChild 、 とは異なりParentます。
  2. のインスタンス クラスParentParentおよび と同じParentです。
于 2015-02-25T20:40:19.887 に答える
0

これは、私がmongoid 3で使用してきた RubyDev のわずかなバリエーションです。

class Parent
  include Mongoid::Document
  validates :column_name , uniqueness: true, unless: Proc.new {|r| r._type == "Child"}
end

class Child < Parent
end

これまでのところ、私にとってはかなりうまくいっています。

于 2013-01-30T07:29:08.393 に答える
0

再びソースを調べてみると、検証はすべての保存時、または更新/作成時にのみ実行できるようです。これは

:validate=> すべての保存
:validate_on_create=> 作成のみ
:validate_on_update=> 更新のみ

write_inheritable_attributeそれらをクリアするには、次のように使用できます。

write_inheritable_attribute :validate, nil
于 2008-11-10T23:47:38.547 に答える