1

アプローチ方法がわからない1つの側面を持つ3つのモデルの関係に取り組んでいます。基本的な関係は次のとおりです。

class Taxonomy
  has_many :terms
  # attribute: `inclusive`, default => false
end

class Term
  belongs_to :taxonomy
  has_and_belongs_to_many :photos
end

class Photo
  has_and_belongs_to_many :terms
end

これは、1つのことを除いて、非常に簡単なことです。

分類法は、「包括的」または「排他的」のいずれかになります。排他的とは、用語が相互に排他的であることを意味し、包括的とは、用語が相互に排他的でないことを意味します。

これで、クライアント側で問題なく処理できるようになりましたが、写真(または他の場所)で基本的に次のような検証を設定する方法がよくわかりません。「排他的な分類法から1つの用語のみを検証します。このレコードに関連付けられています。」

ボーナス質問

また、必須ではありませんが、分類法と写真の間に何らかの結合を設定するとよいと考えていました。つまり、用語で分類されたすべての写真を簡単にクエリできる方法が必要です。与えられた分類法から。

私はこれを次のようなもので行うことができると思いますPhoto.where('term_id in ?', Taxonomy.find(1).terms.map(&:id))が、明らかにそれはあまりエレガントではありません。用語は写真に影響を与えるため、has_many:throughは機能しないと確信しています。そのため、その関係を設定するためのよりエレガントな方法を誰かが知っているなら、それを聞いてみたいと思います。

ありがとう!


分類法のアイデアをさらに説明するために、更新します。

分類法がexclusiveieの場合。taxonomy.inclusive = false、その場合、特定の写真に添付されているその分類からの用語は1つだけです。現在、写真には複数の分類法が適用されている場合があります。例えば:

分類法:色、包括的用語:赤(id 1)、青(id 2)、緑(id 3)

分類法:地域、排他的条件:北アメリカ(id 4)、南アメリカ(id 5)

たとえば、赤と青がたくさん含まれている写真があるとしましょう。これは、これら2つの用語を取得し、南アメリカにある可能性があるため、その用語を取得します。ただし、写真を北米と南米の両方にすることはできません。

したがって、この場合、電話をかけると、次のphoto.terms.map &:idようになります。[1,2,4]

クライアント側では基本的にできる(擬似コード)

form_for photo
- Taxonomy.each do |tax|
  - if tax.inclusive?
    - tax.terms.each do |term|
      - check_box term
  - else
    - tax.terms.each do |term|
      - radio_button term

しかし、モデル側では、写真にはterm_id 1、2、3のいずれかを含めることができますが、4と5のいずれかまたは両方のみを含めることができます。

それは理にかなっていますか?

4

1 に答える 1

2

検証の問題については、分類法が包括的でない場合にのみ実行されるフィールドTermのモデルに一意性の検証を追加できます。taxonomy_id

class Term
  validates :taxonomy_id, uniqueness: true, unless: Proc.new { |term| term.taxonomy.inclusive }
end

カスタム検証方法を使用してこれを行うこともできます。

class Term
  validate :uniqueness_of_taxonomy_if_exclusive

  def uniqueness_of_taxonomy_if_exclusive
    if !taxonomy.inclusive && Term.find_by_taxonomy_id(taxonomy_id)
      errors.add(:taxonomy_id, "already exists for this exclusive taxonomy")
    end
  end
end

この場合、最初の方法でも同じ結果が得られるため、これは役に立たないことに注意してください。ただし、より複雑な検証を行う場合に役立つことがあります。

taxonomy質問の2番目の部分については、ActiveRecordでクエリを作成する方法を次に示します。写真が必要な分類法であると仮定しましょう。

Photo.includes(:terms => :taxonomy).where('taxonomies.id' => taxonomy.id)

コメント後に更新

写真と用語をリンクする表で検証を行う必要があると思います。Railsの規則に従っている場合、それは実際にはテーブルphotos_termsです。検証を追加するには、それを第一級市民にする必要があります。つまり、このテーブルのアクティブレコードモデルとidフィールドを追加します。たとえば、名前を付けますPhotoTermLink。必要な検証のコードは次のとおりです。

class PhotoTermLink
  belongs_to :photo
  belongs_to :term

  validates :term_id, uniqueness: { scope: :photo_id }, unless: Proc.new { |link| link.term.taxonomy.inclusive }
end
于 2012-11-12T07:03:47.053 に答える