2

我的情况与ICtylor 的帖子相似。

所以我有:

user1=User.find(1);
user2=User.find(2);
written=Micropost.where("user_id=2");
written.class #=> ActiveRecord::Relation
written.length   #=> 50
replied=Micropost.where("response = 2 ")  #=> 1
replied.class #=> ActiveRecord::Relation

现在如果我:

alltogether= written + replied;
alltogether.class #=> Array
alltogether.length #=> 51

但是我想要一些相当于做的事情:

all_sql= Micropost.where("user_id = 2  OR response = 2")
all_sql.class #=> ActiveRecord::Relation
all_sql.length #=> 51

换句话说,我想以某种方式将一个找到的记录附加Micropost.where(...)到另一个找到的记录Micropost.where(...)ActiveRecord::Relation对象中。导致相当于all_sql但分两步达到。

一点解释。应用程序的这一部分旨在为回复消息提供类似twitter 的功能。

例如:当用户User.id = 1将此消息发送到User.id=2

@2: hey this is a reply.

Micropost应用程序将使用以下参数创建一个:

@post= Micropost.create(user:1, content:"@2: hey this is a reply", response: 2)

所以response简单地表示回复的接收者ID。如果消息不是回复类型,则response = nil.

按照这个想法,我希望能够:

def replies_to(user)
  Micropost.where("response = #{user.id}")
end

def written_posts_by(user)
  Micropost.where("user_id = #{user.id}")
end

def interesting_posts(user)
  replies= replies_to(user)
  written= written_posts_by(user)
  #And now the question arises!

  new_relation= replies union written#<---How can I do this!?
end
4

3 回答 3

1

这篇博文讨论了这个问题,并提供了一个补丁来在 ActiveRecord 中启用可链接的联合。

于 2013-10-11T18:22:19.620 回答
1

我不认为有内置 Rails 的方法可以在 ActiveRecord::Relation 上进行联合。你最好用 OR 编写一个查询,即使它不是那么干燥。

与阿雷尔:

def interesting_posts(user)
  posts = Micropost.arel_table
  Micropost.where(posts[:response].eq(user.id).or(posts[:user_id].eq(user.id)))
end

使用 SQL:

def interesting_posts(user)
  Micropost.where('response = ? OR user_id = ?', user.id, user.id)
end
于 2013-10-12T00:25:53.803 回答
1

设计本身就有问题,说如果一个帖子回复了两个或更多的接收者怎么办?表中也会有太多的空数据,这不好。

无论如何,基于当前设计仅允许一个接收器,模型需要进行一些更改。

class User < ActiveRecord::Base
  has_many :posts
  has_many :replies, class_name: 'Post', foreign_key: 'response_id'

  def written_posts
    posts
  end

  def posts_replied_to_me
    replies
  end
end

上述变化的注意事项:

  1. API 在用户表中更好,因此它们不需要像(user)
  2. 通过关联,上述两个公共方法实际上是不必要的,仅用于当前目的。您可以直接从关联 API 访问这些帖子。

现在为interesting_posts. 由于上述重构,您不再依赖上述方法来构建聚合查询,因为它们具有不同的结构。Mori 提到的修补是一种解决方案,但如果可能的话,我本人不喜欢触摸 libs。

我更喜欢一种方法来聚合专门针对这种情况的查询。

def interested_posts
  Post.where(interesting_criteria)
end

private
def interesting_criteria
  conditions = []
  conditions << written_by_me
  conditions << replied_to_me
  conditions << foo_bar
  conditions.join(' AND ')
end

def written_by_me
  "user_id = #{self.id}"
end

def replied_to_me
  "response_id = #{self.id}"
end

def foo_bar
  "feel free to add more"
end
于 2013-10-12T03:39:00.210 回答