【问题标题】:Get posts by group in Rails在 Rails 中按组获取帖子
【发布时间】:2015-01-10 13:16:01
【问题描述】:

在我的应用程序中,我有属于组并且可以创建帖子的用户。

在每个组页面上,我试图显示该特定组中用户的所有帖子(从最新到最旧)。这是我迄今为止尝试过的代码,但它显示了每个用户的所有帖子,无论用户属于哪个组。

这是groups_controller.rb

class GroupsController < ApplicationController
  def show
    @group = Group.find(params[:id])
    if logged_in?
      @feed_items = Post.latest_posts_by_group(@group)
    end
  end
end

post.rb:

class Post < ActiveRecord::Base
  belongs_to :user

  def self.latest_posts_by_group(group_id)
    Post.find_by_sql(['select posts.*
      from groups
      inner join users
      on users.group_id = groups.id
      inner join posts
      on posts.user_id = user_id
      where groups.id = ?
      order by created_at desc', group_id])
  end
end

user.rb(嗯,至少是关联):

class User < ActiveRecord::Base
  belongs_to :group
  has_many :posts
end

group.rb(同样,只是显示关联):

class Group < ActiveRecord::Base
  has_many :users
end

【问题讨论】:

  • 可以分享一下模型之间的关系吗?

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


【解决方案1】:

我会使用内置在关联帮助器中的 Rails,而不是手动构建 SQL 查询。在这种情况下

class  Post < ActiveRecord::Base
  belongs_to :user
  has_one :group, through: :user

class  User < ActiveRecord::Base
  belongs_to :group
  has_many :posts

class  Group < ActiveRecord::Base
  has_many :users
  has_many :posts, through: :users

当您正确构建这些关联时,rails 会自动为您生成 @group.posts 之类的方法。

您应该注意,但是必须以某种方式命名外键才能使关联起作用,但是从您的 SQL 查询中,我看到您已经通过命名外键 group_iduser_id 来做到这一点分别在您的 UsersPosts 表中。

更多参考:http://edgeguides.rubyonrails.org/association_basics.html#the-has-many-through-association

【讨论】:

  • 当我尝试这个时,它给了我以下错误:“找不到关联:模型组中的用户”......有什么想法吗?
  • 抱歉,我应该将has_many :users 添加到群组。我现在编辑它。并将 Post 中的 belongs_to :group, through: :user 更改为 has_one,感谢您关注 @Hiasinho
  • 太棒了,这行得通!是否比 Hiasinho 提倡的范围方法更快/更有效?
  • 我不认为你的程序效率有什么区别,但我觉得这种方式可读性更强一些。他们都应该工作。
  • 这种方法(通过关联)更好,因为它更简单。只是想添加一种替代方式。
【解决方案2】:

您可以使用范围来执行此操作。加入:user 关联并在users.group.id 上设置条件。下面的代码应该可以做到。

class Post < ActiveRecord::Base
  belongs_to  :user
  has_one :group, through: :user

  scope :latest_posts_by_group, ->(group) {
    joins(:user).
    where(users: {group_id: group.id}).
    reorder(created_at: :desc)
  }
end

这会创建一个这样的 SQL:

SELECT posts.* FROM posts
  INNER JOIN users ON users.id = posts.user_id
WHERE users.group_id = ?
ORDER BY posts.created_at DESC

如果需要,您还可以考虑groups 表。但这不是必需的,因为 users 表中有 group_id

class Post < ActiveRecord::Base
  belongs_to  :user
  has_one :group, through: :user

  scope :latest_posts_by_group, ->(group) {
    joins(:group).
    where(groups: {id: group.id}).
    reorder(created_at: :desc)
  }
end

这会创建一个这样的 SQL:

SELECT posts.* FROM posts
  INNER JOIN users ON users.id = posts.user_id
  INNER JOIN groups ON groups.id = users.group_id
WHERE groups.id = ?
ORDER BY posts.created_at DESC

查看Rails Guides 了解更多详情。

【讨论】:

  • 谢谢@Hiasinho!对您的第一个建议稍作改动,它就可以工作。我用scope :latest_posts_by_group, -&gt;(group) {joins(:user).where(users: {group_id: group.id}).reorder('created_at desc')}。我希望我能接受不止一次的答案,因为两者都有效并且很有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-13
  • 2020-05-06
  • 2015-04-02
  • 1970-01-01
  • 1970-01-01
  • 2012-08-08
相关资源
最近更新 更多