2016-08-07 13 views
0

Ich versuche zu verhindern, dass Benutzer doppelte Chatrooms erstellen (Chatroom umfasst 2 Benutzer). Aber ich habe keine Ahnung, wie man validiert, ob Chatroom mit den gleichen Benutzern bereits vor dem Speichern existiert. Rails validieren verknüpfte Modelle


Das ist meine Methode in Chatroom-Controller erstellen:

def create 
    @chatroom = Chatroom.new 
    @friend = User.where(username: params[:friend]).last 

    @chatroom.chatroom_users.build(user: @friend, chatroom: @chatroom) 
    @chatroom.chatroom_users.build(user: current_user, chatroom: @chatroom) 

    if @chatroom.save 
     flash[:notice] = "chatrooom created" 
     redirect_to @chatroom 
    else 
     flash[:notice] = "chatrooom not created lol" 
     redirect_to authenticated_root_path 
    end 
end 

Und das ist, wie ich sich zu validieren versuchen, wenn kein Chatroom mit 2 Benutzern wie die neuen ist:

In meiner Klasse Chatroom

after_save :duplicate? 

    # Checks if chatroom containing specific users exists. 
    def duplicate? 
    user = self.users.first 
    friend = self.users.second 

    # lines below work fine - they check if there is already such chatroom 
    (Chatroom.all - [self]).each do |chatroom| 
     if ((chatroom.users & [user, friend]) - [user, friend]).empty? 
     self.errors.add(:chatroom, "Such chatroom already exists.") 
     end 
    end 

    end 

Das Problem ist: wenn ich after_save in validatin verwenden g Methode kann ich die self.users.first Benutzer- und Freund Variablen setzen, aber dann hört es nicht von der Erstellung dieses Datensatzes und ich bin mir nicht sicher, ob es eine gute Idee ist, wenn es löschen. Zweitens - ich verwende validate anstelle von after_save self.users.first und self.users.second gibt nil zurück, damit ich nicht nach Duplikaten suchen kann.

PS: Ich möchte nicht Benutzer-ID als die Attribute in der Chatrooms-Tabelle haben, weil ich die Fähigkeit hinzufügen möchte, um für so viele PPL, wie Sie wollen, zu chatten verbinden.

+0

sicher 'self.users.first' und' self.users.second' sind gleich Null vor Speichern, aber können Sie stattdessen nicht 'user_id' validieren? – kasperite

Antwort

2

Wie wäre es mit so etwas?

def duplicate? 
    is_duplicate = (Chatroom.all.to_a - [self]).any? do |chatroom| 
     chatroom.users.map(&:id).sort == self.chatroom_users.map(&:user_id).sort 
    end 

    if is_duplicate 
     errors.add(:chatroom, "Such chatroom already exists.") 
    end 
    end 

Hier sind alle Modelle.

class ApplicationRecord < ActiveRecord::Base 
    self.abstract_class = true 
end 

class Chatroom < ApplicationRecord 
    has_many :chatroom_users, :dependent => :destroy 
    has_many :users, :through => :chatroom_users 

    before_validation :duplicate? 

    def duplicate? 
    is_duplicate = (Chatroom.all.to_a - [self]).any? do |chatroom| 
     chatroom.users.map(&:id).sort == self.chatroom_users.map(&:user_id).sort 
    end 

    if is_duplicate 
     errors.add(:chatroom, "Such chatroom already exists.") 
    end 
    end 
end 

class ChatroomUser < ApplicationRecord 
    belongs_to :chatroom 
    belongs_to :user 
end 

class User < ApplicationRecord 
    has_many :chatroom_users, :dependent => :destroy 
    has_many :chatrooms, :through => :chatroom_users 
end 

Und hier ist ein Test

require 'test_helper' 

class ChatroomTest < ActiveSupport::TestCase 
    # test "the truth" do 
    # assert true 
    # end 

    test 'does not allow duplicate chatrooms' do 
    first_user = User.create! 
    second_user = User.create! 

    chatroom = Chatroom.create! 
    chatroom.chatroom_users.build(user: first_user, chatroom: chatroom) 
    chatroom.chatroom_users.build(user: second_user, chatroom: chatroom) 
    chatroom.save! 

    duplicate_chatroom = Chatroom.create! 
    duplicate_chatroom.chatroom_users.build(user: first_user, chatroom: chatroom) 
    duplicate_chatroom.chatroom_users.build(user: second_user, chatroom: chatroom) 

    assert !duplicate_chatroom.valid? 
    end 
end 

Hinweis: Dieser Code ist in Rails 5.

+0

Es funktioniert perfekt! Danke für diese großartige Antwort. Ich frage mich nur - warum es jetzt funktioniert, aber mit 'chatroom.users.map (&: id) .sort == self.users.map (&: id) .sort' geht es nicht? –

+1

Das funktioniert nicht, da die Benutzer-IDs noch nicht gespeichert sind, so dass die Verknüpfung noch nicht funktioniert. Aber user_id funktioniert, weil diese im Modell gespeichert sind. – kcdragon