Getting Cancan's load_and_authorize_resource working within a custom create action
Asked Answered
F

3

6

Trying to set up Cancan within an app of mine and having trouble with my PostsController.

In a nutshell, when a Post is created I'd like it associated with the current_user so my create action looks something like this:

class PostsController < ApplicationController
  before_filter :login_required, :except => [:index, :show]
  load_and_authorize_resource
  ...
  def create
    # @post = Post.new(params[:post])   # <-- covered by load_and_authorize_resource
    @user = current_user
    @post = @user.posts.create(params[:post])
    respond_to do |format|
    ...
  end
  ...
end

I'm not exactly sure what load_and_authorize_resource is intended to do (other than the obvious). But what about in a situation like this? Do I need to override the load_and_authorize_resource for the create action somehow? or is there another (read: better) way to go about loading the @user and THEN creating the @post?

Fredel answered 10/8, 2011 at 17:42 Comment(0)
H
3

A simpler solution to your problem would be to use a nested-resource, rather than creating a custom action

Directly taken from the CanCan Wiki:

Nested-Resources

As of 1.4, it's also possible to nest through a method, this is commonly the current_user method.

 class ProjectsController < ApplicationController
   load_and_authorize_resource :through => :current_user
 end 

Here everything will be loaded through the current_user.projects association.

This should be safer as well, as loading of a post will be done through the association for other actions in your controller

Honkytonk answered 2/4, 2012 at 13:56 Comment(1)
What about error coming if accessing project of another user from controller. It is throwing error Couldn't find Project with 'id'=<another_user_project_id> [WHERE projects.user_id` = ?] `Monosepalous
K
12

I think the best solution, since this is a unique problem, for you to alter load_and_authorize_resource line to this:

load_and_authorize_resource :except => [:create]

And the action to this:

def create
  authorize! :create, Post
  current_user.posts.create(params[:post])
end
Kneedeep answered 10/8, 2011 at 18:31 Comment(1)
Works great for me. You may add :new to :except as well.Asshur
H
3

A simpler solution to your problem would be to use a nested-resource, rather than creating a custom action

Directly taken from the CanCan Wiki:

Nested-Resources

As of 1.4, it's also possible to nest through a method, this is commonly the current_user method.

 class ProjectsController < ApplicationController
   load_and_authorize_resource :through => :current_user
 end 

Here everything will be loaded through the current_user.projects association.

This should be safer as well, as loading of a post will be done through the association for other actions in your controller

Honkytonk answered 2/4, 2012 at 13:56 Comment(1)
What about error coming if accessing project of another user from controller. It is throwing error Couldn't find Project with 'id'=<another_user_project_id> [WHERE projects.user_id` = ?] `Monosepalous
L
0

This solution worked for me too

authorize_resource class: 'User'

Lancelle answered 3/4, 2020 at 11:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.