2014-02-27 74 views
1

我的模型結構,建立這樣的,軌有許多地方通過查詢

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個用戶可以進行對話。現在我的查詢是查找包括用戶標識的對話,但可能包括與大型團體的對話。我控制器查詢看起來是這樣的,

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 

上處理的最佳方式是任何想法?

回答

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) 
+0

十分感謝!出於某種原因,我的通知沒有彈出答案。 –

+0

甚至不知道你可以做到這一點。再次感謝。 –