3

私は、子の属性を検証するために親からの値を使用する必要がある単純な親子関係を持つ Rails 3.2 アプリケーションを持っています。モデルは次のようになります。

class RubricItem < ActiveRecord::Base
  attr_accessible :max_score, :min_score, :name, :order
  has_many :rubric_ranges
end

class RubricRange < ActiveRecord::Base
  attr_accessible :helper, :range_max, :range_min, :rubric_item_id
  validates_presence_of :helper, :range_max, :range_min
  validates :range_max, :range_min, :numericality => {:only_integer => true}
  validates :range_max, :numericality => { :greater_than => :range_min }
  belongs_to :rubric_item
end

2つの異なることを検証できるようにしたい。まず、rubric_range について、range_min 値が親 rubic.min_score に対して >= であり、range_max <= 親 rubric.max_score に対してであることを検証します。

次に、他の rubric_ranges に固有の最小値/最大値があることを検証したいと思います。つまり、同じ値に対して 2 つの rubric_ranges を定義することはできないため、1 つが 0 ~ 2 をカバーする場合、別のものがその範囲に 0、1、または 2 を含んではなりません。例: 最初の範囲は 0 ~ 2 です。2 ~ 4 の範囲を定義する場合、親のスコープ内で検証エラーを発生させたいと考えています。

助けてくれてありがとう。

4

1 に答える 1

2

親を使用するほぼ通常の方法で親を使用できます。

class RubricRange < ActiveRecord::Base
  ...
  validate :has_proper_range
  ...
  def has_proper_range
    error.add(:range_min, ' cannot be smaller than RubricItem minimum score') if range_min < rubric_item.min_score
    error.add(:range_max, ' cannot be greater than RubricItem maximum score') if range_max > rubric_item.max_score
  end

唯一の問題は、nested_attributes を使用して RubricRange アイテムを RubricItem と一緒に作成する場合です。これは、関連付けのビルド メソッドが新しいレコードの逆の関係を設定しないためです。

2 番目の検証は、指定された範囲内に最小値または最大値を持つ他の範囲がある場合に失敗することに注意するだけで実行できます。したがって:

validate :do_not_overlap_with_other_ranges
...
def do_not_overlap_with_other_ranges
  overlapping_ranges = self.class.where('(range_min >= :min AND range_min <= :max) OR (range_max >= :min AND range_max <= :max)', {:min => range_min, :max => range_max})
  overlapping_ranges = overlapping_ranges.where.not(:id => id) unless new_record?
  errors.add(:base, 'Range overlapping with another range') if overlapping_ranges.exists?
end

(これを書くにはもっと良い方法があるはずだと思うので、上記のクエリについて気軽にコメントしてください)。

于 2013-09-09T14:07:22.877 に答える