2016-08-07 5 views
0

Я пытаюсь запретить пользователям создавать повторяющиеся чаты (в чате есть 2 пользователя). Но я понятия не имею, как проверить, существует ли чат с теми же самыми пользователями, которые уже существуют до сохранения. Rails проверяет связанные модели


тот мой метод создания в контроллере Chatroom:

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 

И это, как я пытаюсь проверить, если нет Chatroom 2 пользователей как новый:

В моем классе 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 

проблема заключается в том:, если я использую after_save в validatin g метод Я могу получить self.users.first, чтобы установить переменные пользователя и друга, но затем он не останавливается на создании этой записи, и я не уверен, что если ее удалить, есть хорошая идея. Во-вторых - я использую validate вместо after_save self.users.first и self.users.second возвращает nil, поэтому я не могу проверить наличие дубликатов.

PS: Я не хочу иметь идентификаторы пользователей в качестве атрибутов в таблице чатов, потому что я хочу добавить возможность подключения к чату столько раз, сколько вы хотите.

+0

безусловно '' self.users.first' и self.users.second' равны нулю, прежде чем сохранить, но вы не можете проверить вместо этого 'user_id'? – kasperite

ответ

2

Как насчет чего-то подобного?

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 

Все модели.

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 

И вот это испытание

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 

Примечание: Этот код в Rails 5.

+0

Он отлично работает! Спасибо за этот отличный ответ. Мне просто интересно - почему это работает сейчас, но с 'chatroom.users.map (&: id) .sort == self.users.map (&: id) .sort' его нет? –

+1

Это не работает, потому что идентификаторы пользователей еще не сохраняются, поэтому связь еще не работает. Но user_id работает, потому что они хранятся в модели. – kcdragon

Смежные вопросы