Retrieve all Project Threads where a given users has posted a Project Post
A user belogns to a ProjectThread. And a ProjectThread has_many Users through ProjectPosts.
On the Project Thread Index I want to display only threads where a given users has posted a Project Post.
How would I go about doing that?
class ProjectThreadsController < ApplicationController
def index
@project_thread = if current_user.project_posts.any?
ProjectThreads.all
end
end
There might be a slicker way, but this works:
ProjectThread.find(current_user.project_posts.pluck(:project_thread_id).uniq)
This will select all the current_users project_posts, pluck the ID's of the project_thread_id, then call uniq to ensure that if a user had multiple posts in a single thread, you won't get duplicate threads.
And just to make sure, your description of how you have your models setup doesn't sound right. They should be like this:
# user model
class User < ApplicationRecord
has_many :project_threads, through: :project_posts
has_many :project_posts
end
# project_thread model
class ProjectThread < ApplicationRecord
has_many :users, through: :project_posts
has_many :project_posts
end
# project_post model
class ProjectPost < ApplicationRecord
belongs_to :user
belongs_to :project_thread
end
Check: http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association
Jacob thanks! ProjectThread.find(current_user.project_posts.pluck(:project_thread_id).uniq)
worked!
How would would I create a private method to prevent other users from accessing Project Threads that dont belong to them?
I currently have something like this:
def require_permission
if current_user != ProjectThread.friendly.find(params[:id]).user
redirect_to root_path
end
end
But this only works if the user is the ProjectThread owner.
And currently I have my models setup like this. it seems to be working okay.
class User < ApplicationRecord
has_many :project_threads
has_many :project_posts
end
class ProjectThread < ApplicationRecord
belongs_to :user, optional: true
has_many :project_posts
has_many :users, through: :project_posts
end
class ProjectPost < ApplicationRecord
belongs_to :user, optional: true
belongs_to :project_thread, optional: true
end
You need another table that handles assignments to threads.
# project_thread_access model
# you'll need user_id and project_thread_id columns in this model
belongs_to :project_thread_accessable, :polymorphic => true
# project_thread model
has_many :project_thread_access, as: :project_thread_accessable
# user model
has_many :project_thread_access, as: :project_thread_accessable
This would let you do something like:
current_user.project_thread_access
which would return a list of project_threads that user has been assigned to.
Now, you can do something like:
def show
redirect_to root_url, alert: "Sorry, but you do not have access to this thread" unless current_user.project_thread_access.pluck(:project_thread_id).include?(params[:id])
end
*updated redirect - alert needs to be before the condition
I haven't tested this, so it may need some tweaking - but you should get the idea