Я пытаюсь настроить систему обмена сообщениями, похожую на Facebook, где у вас есть список сообщений, отсортированных по разговорам между двумя пользователями (в данный момент это не важно для нескольких получателей, но, возможно, если бы я использовал более умный дизайнтогда это может быть легко реализовано в будущем. Я не думаю, что было бы легко добавить к тому, что у меня есть в настоящее время.) У меня есть что-то вроде работы, но я не могу реализовать некоторые функции.Я довольно плохо знаком с рельсами / веб-программированием, поэтому любые советы / подсказки / решения очень ценятся.
Итак, у меня есть три соответствующие модели: пользователь, беседа и сообщения.У пользователя много бесед, в разговоре много сообщений и он принадлежит пользователям, а сообщение принадлежит разговору.Итак, вот как выглядят модели:
Пользователь: имеет соответствующие поля ID: int, имя пользователя: строка
class User < ActiveRecord::Base
has_many :conversations, :class_name => "Conversation", :finder_sql =>
proc {
"SELECT * FROM conversations " +
"WHERE conversations.user1_id = #{id} OR conversations.user2_id = #{id} " +
"ORDER BY conversations.updated_at DESC" }
Диалог: имеет соответствующие поля: ID: int, user1_id:int, user2_id: int, user1_deleted: логический, user2_deleted: логический, созданный_ат: datetime, updated_at: datetime
class Conversation < ActiveRecord::Base
has_many :messages
belongs_to :participant_one, :class_name => "User", :foreign_key => :user1_id
belongs_to :participant_two, :class_name => "User", :foreign_key => :user2_id
private
def self.between(user1, user2)
c = Conversation.arel_table
Conversation.where(c[:user1_id].eq(user1).and(c[:user2_id].eq(user2)).or(c[:user1_id].eq(user2).and(c[:user2_id].eq(user1))))
Сообщение: имеет соответствующие поля: id: int, journal_id: int, author_id: int, content:text, create_at: datetime, updated_at: datetime
class Message < ActiveRecord::Base
belongs_to :conversation, :touch => true
Я не совсем уверен, нужны ли мне member_one и member_two, но я использую
def conversation_partner(conversation)
conversation.participant_one == current_user ? conversation.participant_two : conversation.participant_one
end
в ConversationHelper, чтобы в представленияхЯ могу показать другому участнику.
Так что это в основном работает.Но одна из сложностей, с которыми я столкнулся, заключается в том, что я не очень хорошо различаю пользователей в беседе, пользователь может находиться либо в поле user1, либо в user2.Поэтому мне нужно постоянно искать пользователя в том или ином поле, например, в finder_sql в объявлении пользователя has_many.Кроме того, когда я создаю новое сообщение, я сначала ищу, чтобы увидеть, есть ли параметр Conversation, или если нет, посмотрите, есть ли диалог между двумя пользователями, и если нет, то создайте новый диалог.(Вы можете либо отправить сообщение из индекса разговора (например, ответ), либо current_user может просматривать другого пользователя и щелкнуть ссылку «отправить этому пользователю сообщение». Контроллер сообщений выглядит следующим образом и использует его самостоятельно.Между методом в модели беседы:
class MessagesController < ApplicationController
before_filter :get_user
before_filter :find_or_create_conversation, :only => [:new, :create]
def new
@message = Message.new
end
def create
@message = @conversation.messages.build(params[:message])
@message.author_id = current_user.id
if @message.save
redirect_to user_conversation_path(current_user, @conversation), :notice => "Message sent!"
else
redirect_to @conversation
end
end
private
def get_user
@user = User.find(params[:user_id])
end
def find_or_create_conversation
if params[:conversation_id]
@conversation = Conversation.find(params[:conversation_id])
else
@conversation = Conversation.between(@user.id, current_user.id).first or @conversation = Conversation.create!(:user1_id => current_user.id, :user2_id => @user.id)
end
end
(мои маршруты выглядят так:)
resources :users do
resources :conversations, :only => [:index, :create, :show, :destroy] do
resources :messages, :only => [:new, :create]
end
resources :messages, :only => [:new]
end
Так что теперь у меня возникают проблемы при попытке установить флаги user1_deleted или user2_deleted. (и точно так же, если / когда я реализую флаг чтения / обновления). Проблема в том, что, поскольку один и тот же пользователь может иметь много разговоров, но он может быть либо пользователем 1, либо пользователем 2, его становится трудно найти.думал, что я могу сделать что-то вроде этого в модели разговора:
def self.active(user)
Conversation.where(which_user?(user) + "_deleted = ?", false)
end
def self.which_user?(user)
:user1_id == user ? 'user1' : 'user2'
end
Но тогда вы не сможете запустить весь разговор, если не будете перебирать каждый разговор пользователя по очереди, потому что иногда онuser1, а иногда он и пользователь 2. Должен ли я отказаться от всего этого подхода и попробовать новый дизайн? Если да, кто-нибудь возможный подходh что будет более элегантно / лучше работать / на самом деле работать и по-прежнему отвечать тем же потребностям?
Это довольно длинный вопрос, поэтому я ценю любого, кто готов пройти через все это со мной.Спасибо.