2017-11-23 1 views
-1

Ich habe tre ModelleAngepasste Validierung für einen Rails Verein

class ChallengeItem < ApplicationRecord 
    has_many :photos 
end 

class Photo < ApplicationRecord 
    belongs_to :challenge_item 
    has_many :votes 
end 

class Vote < ApplicationRecord 
    belongs_to :photo 
    validate :vote_per_foto 

    private 

    def vote_per_foto 
    if self.class.exists?(photo_id: photo_id, voter_string: voter_string) 
     errors.add :vote, 'already voted' 
    end 
    end 
end 

Grundsätzlich für jede Gruppe von Fotos (ChallengeItem) Benutzer nur ein Foto abstimmen. Jede Stimme hat ein Fingerabdruck-Attribut, genannt voter_string

Ich schreibe eine benutzerdefinierte Validierung, aber mit dieser Validierung akzeptiere ich nur eine Stimme für Foto. Ich brauche eine Stimme für jede Gruppe von Fotos ...

Wie kann ich es beheben?

Antwort

1

Suchen Sie nach dem #uniqueness Validator mit der Option scope, um einen verknüpften Datensatz zu begrenzen. Sie können so etwas wie

validates :voter_string, uniqueness: { scope: { :photo_id } } 

zu bekommen nur eine Vote mit einer bestimmten voter_string pro gegebenen photo_id tun.

+0

ist nicht was ich brauche. Ich brauche keine Stimme für photo_id, ich brauche eine Stimme für challenge_item.photos –

+0

Ich missverstanden. Wenn es eine 1 "Vote" pro "ChallengeItem" gibt, warum hast du dann keine direkte "gehört_zu" Beziehung zwischen den beiden Modellen? –

+0

Weil die Leute für jedes Challenge-Item das beste Foto wählen müssen. Die Stimme gehört dem Foto ... aber sie können nur ein Foto wählen –

0

Sie müssen überprüfen, ob die Abstimmung für alle Fotos in der challenge_item existiert:

def vote_per_foto 
    if self.class.exists?(photo_id: photo.challenge_item.photos.select(:id), voter_string: voter_string) 
    errors.add :vote, 'already voted' 
    end 
end 
0

Was möchten Sie tun, ist Setup eine indirekte Assoziation:

class ChallengeItem < ApplicationRecord 
    has_many :photos 
    has_many :votes, through: :photos 
end 

class Photo < ApplicationRecord 
    belongs_to :challenge_item 
    has_many :votes 
end 

class Vote < ApplicationRecord 
    belongs_to :photo 
    has_one :challenge_item, through: :photo 
    validate :one_vote_per_challenge_item 

    def one_vote_per_challenge_item 
    if challenge_item.votes.exists?(voter_string: voter_string) 
     errors.add :base, 'already voted' 
    end 
    end 
end 

So können Sie challenge_item zugreifen von einer Fotoinstanz und Rails übernimmt den Beitritt für Sie.

+0

Da jedoch kein Datenbankindex die Einzigartigkeit unterstützt, kann es anfällig für Race Conditions sein. – max

Verwandte Themen