Search code examples
ruby-on-railscontrollerhas-and-belongs-to-manymodel-associations

Has_and_belong_to_many association


I have two models with no associations between them. So, I generated a migration and added an 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

I currently have a page where all the posts are shown. However, I added a multi select in the post creation form in order to select one workspace or more when creating. I would like to be able to show only the posts that were created for that particular workspace instead of all of them, as it is at the moment. My controller is as follows:

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

I am able to get the associated workspace this way:

Post.first.workspaces

But I would like to show all the posts and I get an error when I try this command:

Post.all.workspaces

How could I change my controller and accomplish that? Thank you in advance for your help!


Solution

  • Well you should have a table called PostsWorkspaces by rails convention so you should be able to do something like:

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

    The above will return the posts that have at least one workspace associated, the problem with the approach Post.all.workspaces is that not all posts need to have a workspace (or more than one) associated, also you can think on Post.all like select * from posts which is not what you want to accomplish.

    Hope the above helps! 👍