代码之家  ›  专栏  ›  技术社区  ›  JoshReedSchramm

如何找到与其他模型无关的所有项-Rails 3

  •  1
  • JoshReedSchramm  · 技术社区  · 16 年前

    我有两个模型,用户和地点。

    一个用户与Place有两次关联。一次用于参观的地方,一次用于规划的地方。这是一个多对多的关系,但使用有很多:通过。这是来自用户的关系。

    has_many :visited_places
    has_many :visited, :class_name=>"Place", :through=>:visited_places, :source=>:place
    
    has_many :planned_places
    has_many :planned, :class_name=>"Place", :through=>:planned_places, :source=>:place
    

    在适当的地方,关系也被定义。这是这里的定义

    has_many :visited_users, :class_name=>"User", :through=>:visited_places  
    has_many :planned_users, :class_name=>"User", :through=>:planned_places
    

    我正在尝试编写一个find-on-Place,它返回数据库中所有与某个用户无关的地方,无论是访问的还是计划的。现在我只需查询所有地方,然后从结果中减去访问和计划,就可以实现这一点,但我想添加分页,我担心这会使问题复杂化。这是我现在的密码。

    all_places = Place.find(:all)        
    all_places = all_places - user.visited - user.planned
    

    任何人都知道我是如何做到这一点的,只要打个电话找地方。此外,这是一个Rails3应用程序,所以如果任何活动记录的改进使这更容易,他们是一个选择。

    4 回复  |  直到 16 年前
        1
  •  2
  •   John Bachir    16 年前

    unvisited_places = Place.find(:all, :conditions => "id NOT IN(#{visited_places.map(&:place_id)})")
    

    这就是总体思路——它可以根据您的最终需求变得更加高效和方便。

        2
  •  0
  •   bjg    16 年前

    你没有表现出来,但如果我认为 VisitedPlace 和 PlannedPlace 模型有一个 belongs_to :user 那么这些表有一个 user_id

    因此,在这种情况下,我认为在数据库中这样做是最有效的,在这种情况下,您将在连接的表中查找select places , visited_places planned_places users.id 两个都不在 参观过的地方 规划的\u地点

        3
  •  0
  •   nathanvda    16 年前

    在sql中:

    select * from places where id not in 
      (
        (select place_id from visited_places where user_id = ?) 
      union 
        (select place_id from planned_places where user_id=?)
      )
    

    如果该查询有效,则可以使用以下命令:

    Places.find_by_sql(...the complete sql query ...)
    

    否则,我不知道如何在Rails3中编写这样一个带有排除项的查询。

        4
  •  0
  •   pdobb    12 年前

    Model1.where.not(id: Model2.select(:user_id).uniq)
    

    这将创建一个嵌套的SELECT,就像@nathanvda建议的那样,有效地让数据库完成所有工作。生成的SQL示例如下:

    SELECT "model1s".* FROM "model1s"  WHERE ("model1s"."id" NOT IN (SELECT DISTINCT "model2s"."model1_id" FROM "model2s"))