Rails&活动记录:查找其子女不属于current_user或没有孩子的对象

时间:2016-09-22 05:53:15

标签: ruby-on-rails activerecord

User.rb

 try {
            synchronized (LOCK_OBJCT) {
                if (_conn == null || _conn.isClosed()) {
                    Class.forName(DB_DRIVER);
                    logger.debug("Connecting to: " + DB_URL + "; as: " + DB_USERID);
                    _conn = DriverManager.getConnection(DB_URL, DB_USERID, DB_PASSWORD); 
                    _conn.setAutoCommit(false);
                } 
                else {
                    logger.debug("Connected to: " + DB_URL + "; as: " + DB_USERID);
                }
            }
        } catch(ClassNotFoundException ce) {
            logger.error("Error when obtaining JDBC driver.Exiting...", ce);
            System.exit(1);
        } catch(SQLException e) {
            logger.error("Error when obtaining insight db conn: " + DB_URL + "; as: " + DB_USERID + " Exiting..." , e);
            System.exit(1);
        }

        return _conn;
    }`

Event.rb

 has_many :votes

Vote.rb

  has_many :votes

我正在尝试渲染current_user尚未投票的所有事件。

考虑这种情况:

  • 有100个活动 belongs_to :user belongs_to :event
  • 用户已投票选出5个活动Event.includes(:votes).count ==> 100
  • 有75个事件至少有一个来自其他用户的投票
  • 其中20个活动尚未收到任何用户
  • 的投票

我正在寻找的结果应该呈现current_user尚未投票的95个事件,包括任何用户未投票的事件。

此查询获取所有没有用户投票的事件:

current_user.votes.count ==> 5

我可以使用什么查询来获取用户已经投票的所有事件,但当前用户已投票的那些事件(在上面的示例中应该返回75)?我尝试了下面的查询,但它返回80(由current_user投票的包含事件):

Event.includes(:votes).where(:votes => {:id => nil}).references(:votes).count ==> 20
  1. 我可以使用什么查询来获得投票活动,不包括当前用户投票的
  2. 我可以将两个查询合并为一个吗?

4 个答案:

答案 0 :(得分:1)

我可以将两个查询合并为一个吗?

如果要使用AND组合使用merge

results = frecords.merge(lrecords)

如果要使用OR组合,请使用或(仅在ActiveRecord 5 +中可用):

results = frecords.or(lrecords)

答案 1 :(得分:1)

Hacky但有趣的回答

class Event
  has_many :votes
  has_many :user_votes,
             ->() { where({user_id: Thread.current[:user]&.id}.compact) },
             class_name: 'Vote'

  def self.using_user(user)
    old_user, Thread.current[:user] = Thread.current[:user], user
    yeild
  ensure
    Thread.current[:user] = old_user
  end
end

Event.using_user(current_user) do
  Event.includes(:user_votes).where("votes.id IS NULL")
end

原始答案:

Event.
  joins(
   "LEFT OUTER JOIN votes ON votes.event_id = events.id AND " +
   "votes.user_id = #{user.id}"
  ).
  where("votes.id IS NULL")

答案 2 :(得分:0)

  
      
  1. 我可以使用什么查询来获得投票活动,不包括当前用户投票的活动。
  2.   
events_current_user_voted_on = current_user.votes.pluck(:event_id) 
events_all_users_voted_on = Vote.pluck(:event_id).uniq

events_only_others_voted_on = events_all_users_voted_on - events_current_user_voted_on

# 75 events with at least one vote from other users
Event.where(id: events_only_others_voted_on)

答案 3 :(得分:0)

回答第一个问题: 我已经修改了你尝试过的查询,所以试试这个

Event.includes(:votes).where.not(:votes => {:user_id => current_user}).references(:votes).count

注意到哪里的条件。您需要查看user_id votes列 或者您可以尝试字符串语法:

Event.includes(:votes).where.not("votes.user_id" => current_user).references(:votes).count

关于你的第二个问题,我不确定我理解你的要求。如果您需要过滤至少投票一次且仅来自其他用户的事件,则只需将另一个添加到where语句中。

Event.includes(:votes).where.not("votes.user_id" => current_user, "votes.user_id" => nil).references(:votes).count

顺便说一句,我认为您在vote.rb中指定了与自身关联的错误,而不是与Event的关联,即belongs_to :event