Has_and_belong_to_many 协会

Has_and_belong_to_many association

我有两个模型,它们之间没有关联。所以,我生成了一个迁移并添加了一个关联。

class Post < ActiveRecord::Base
  has_and_belongs_to_many :workspaces
end
class Workspace < ActiveRecord::Base
  has_and_belongs_to_many :posts
end
class CreateJoinTablePostsUsers < ActiveRecord::Migration
  def change
    create_join_table :posts, :workspaces do |t|
      # t.index [:post_id, :workspace_id]
      # t.index [:workspace_id, :post_id]
    end
  end
end

我目前有一个显示所有 post 的页面。但是,我在post创建表单中添加了一个multi select,以便在创建时select一个或多个工作空间。我希望能够仅显示为该特定工作区创建的 post,而不是像目前那样显示所有这些。 我的控制器如下:

class PostsController < Admin::BaseControlle
  def index
    respond_to do |format|
      format.html
      format.json do
        @posts = Post.all.order(:order)
        render json: present_collection(@posts, PostPresenter).map(&:as_json)
      end
    end
  end

  private

  def post_params
    params.require(:post).permit(:label, :url, :active, workspace_ids: [])
  end
end

我可以通过这种方式获取关联的工作空间:

Post.first.workspaces

但我想显示所有 posts,当我尝试这个命令时出现错误:

Post.all.workspaces

我怎样才能改变我的控制器并实现它?预先感谢您的帮助!

好吧,你应该有一个 table 按照 rails 约定称为 PostsWorkspaces 这样你应该能够做这样的事情:

posts_in_workspaces = PostsWorkspaces.all.pluck(:post_id)
Posts.where(id: posts_in_workspaces )

以上将 return 至少有一个 workspace 关联的 posts,方法 Post.all.workspaces 的问题是并非所有帖子都需要有一个相关的工作空间(或多个),你也可以考虑 Post.all 比如 select * from posts 这不是你想要完成的。

希望以上内容对您有所帮助!

你想错了。 Post.first.workspaces 有效,因为关联应用于返回的 Post 实例。但是Post.allreturns一个集合。

您最好的选择是执行以下操作。

# Return all posts that have a workspace associated
posts = Post.joins(:workspaces).all.distinct

posts.each do |post|
 post.workspaces
end

如果您想包含没有工作区的帖子

posts = Post.includes(:workspaces).all

posts.each do |post|
 post.workspaces
end