【问题标题】:rails has many through where queryrails 有很多通过 where 查询
【发布时间】:2014-02-27 16:13:43
【问题描述】:

我的模型结构是这样设置的,

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

关于处理此问题的最佳方法的任何想法?

【问题讨论】:

    标签: sql ruby-on-rails forms ruby-on-rails-4


    【解决方案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)
    

    【讨论】:

    • 非常感谢!由于某种原因,我的通知中没有弹出答案。
    猜你喜欢
    • 2018-01-28
    • 1970-01-01
    • 1970-01-01
    • 2012-03-17
    • 2021-11-16
    • 2017-04-25
    • 1970-01-01
    • 1970-01-01
    • 2019-05-24
    相关资源
    最近更新 更多