我的模型结构设置如下,
class Conversation < ActiveRecord::Base
has_many :conversation_statuses, :dependent => :destroy
has_many :users, :through => :conversation_statuses
has_many :messages, :inverse_of => :conversation
accepts_nested_attributes_for :messages
end
class User < ActiveRecord::Base
has_many :conversation_statuses, :dependent => :destroy
has_many :conversations, :through => :conversation_statuses
has_many :messages, :inverse_of => :user
end
class ConversationStatus < ActiveRecord::Base
belongs_to :user
belongs_to :conversation
end
我只是在用户没有进行对话时才尝试创建对话。我设置了对话,以便超过2个用户可以进行对话。现在我的查询是查找包括用户ID的对话,但可能包括与大组的对话。我的控制器查询看起来像这样,
class ConversationsController < ApplicationController
before_filter :set_user_ids_param, :only => :create
def create
@conversation = Conversation.joins(:users)
.where(:users => {:id => params[:conversation][:user_ids]})
.first_or_initialize
@conversation.attributes = conversation_params
if @conversation.save
render :json => { :html => render_new_conversation_form }
return
end
render :status => :bad_request, :json => {
:html => render_conversation_form
}
end
private
def conversation_params
params.require(:conversation).permit([
:user_ids => [],
:messages_attributes => [
:content,
:topic
]
])
end
def set_user_ids_param
return if params[:conversation].blank?
return if params[:conversation].blank? || params[:conversation][:user_ids].blank?
params[:conversation][:user_ids] = params[:conversation][:user_ids].split(',')
params[:conversation][:user_ids].push(current_user.id)
end
def render_new_conversation_form
render_to_string({
:partial => 'conversations/form',
:locals => {
:conversation => @conversation
}
})
end
def render_conversation_form
render_to_string({
:partial => 'conversations/form',
:locals => {
:conversation => @conversation
}
})
end
end
我的表单看起来像这样
= simple_form_for conversation, :html => {:class => 'conversation-form'} do |form|
= form.input :user_ids, :as => :hidden, :input_html => {:class => 'user-ids'}
= form.simple_fields_for :messages do |message_fields|
= render 'messages/fields', :message_fields => message_fields
%button.button.radius.submit.no-margin
Send Message
%button.button.secondary.radius.cancel.no-margin
Cancel
有关处理此问题的最佳方法的任何想法吗?
答案 0 :(得分:1)
解决问题的方法应该在课程ConversationStatus
中,如果存在,则会为您提供对话的conversation_id
。
你需要两套:
containing_all_users
是包含users_id
with_extra_users
是包含的用户数多于users_id
对话(如果存在)是减去这些集合的结果。
class ConversationStatus < ActiveRecord::Base
belongs_to :user
belongs_to :conversation
def self.find_between(user_ids)
containing_all_users = group(:conversation_id)
.where(user_id: user_ids)
.having(['COUNT(user_id) = ?', user_ids.length])
.pluck(:conversation_id)
with_extra_users = group(:conversation_id)
.having(['COUNT(user_id) > ?', user_ids.length])
.pluck(:conversation_id)
(containing_all_users - with_extra_users).first
end
end
您将从Conversation
模型中获得对话。您也应该在此方法上设置属性:
class Conversation < ActiveRecord::Base
has_many :conversation_statuses, dependent: :destroy
has_many :users, through: :conversation_statuses
def self.find_between(user_ids, attributes = {})
conversation_id = ConversationStatus.find_between(user_ids)
Conversation.where(id: conversation_id).first_or_initialize(attributes)
end
end
在控制器上你会这样称呼它:
@conversation = Conversation.find_between(params[:conversation][:user_ids],
conversation_params)