I was trying to use CanCan with Inherited Resources but I got to a problem when using the "authorize_resource" alone, without "load_resource".
This method ends up counting on an instance variable @model but that doesn't get set when using Inherited Resources until you call the "resource" helper (lazy loading). The way to make it work would be fetching it from the "resource" helper.
What do you think of adding a param/option to "authorize_resource" which would allow determining an alternative strategy of fetching the resource?
There are a number of other resource loading utilities (such as make_resourceful) and ideally these should be supported as well.
The lazy loading method does seem like a popular approach which several of them use so I think this is definitely worth adding. How about an :accessor_method option?
authorize_resource :accessor_method => :item
Any suggestions for an alternative name?
I'm not a fan of this name but couldn't think of anything better. =)
Would you be interested in a patch?
Happy new year!
On my app I just extended InheritedResource with the following code:
unauthorized! if cannot?(params[:action].to_sym, asset)
@asset ||= case params[:action].to_sym
when :new, :create
resource || resource_class
then I just do a before_filter :authorized?
I like this method because it makes it just work if you are using inherited_resource. I will fork and add as a patch if interested.
Hey @hexorx, thanks for the heads up. It made cancan work immediately with IR which is great.
As per a definitive solution I'd go the way Ryan suggested.
After some study it seems the place to handle the option would be ControllerResource::model_instance.
However, to call the accessor_method from there, I'd need to do the same checks that are done at ResourceAuthorization regarding collection_actions and new_actions in order to just call the accessor when appropriate.
I thought it'd be a good idea to validate the approach before moving on.
@hexorx, thanks. I was going to leave the CanCan due to this same error while I was using it with IH. But the hack worked for me as well.
I just love both CanCan and IH in combination.
Seeing the hack, I realize this problem is more complex then I first assumed. There isn't just a single accessor method which returns an object in various states (new, existing, etc) but multiple methods to help build the resource. Therefore I don't think a simple option will be sufficient because it is very specific to ResourceAuthorization.
Probably the best thing is to deal with ResourceAuthorization directly and detect if it is being used. It would be nice to abstract this out so it works with other resource loading plugins as well. I'm not certain when I will get around to this, so if someone wants to work on this in a fork, be my guest. :)
Hi Ryan, et. al.
I am using cancan (v1.1.1) with inherited_resources (v 1.0.6) and work excellent with one exception.
When I have a IR controller that has a belongs_to relationship and I add 'load_and_authorize_resource' into it, IR is missing the respected association id when doing an insert of a new record. It has the field in it's sql insert, but only a null value. When I remove load_and_authorize_resource the belongs_to id is included. This seems to be a big problem because the insert continues and I would be left to believe that everything worked correctly. I have been thinking about going thru your code and writing a patch but I was wondering if anyone here had already done so.
Anyway, thanks for the great plugin Ryan. This has become a big part of my app.
All the best,
So my belongs_to problem about is easily fixed (or so it seems right now) if you just add except:
load_and_authorize_resource :except => [:create, :update]
this is because cancan is trying to load/build all resources...so it Inherited Resources however cancan doesnt know about a belongs_to function and doesnt add in the respected belongs_to association id. Anyway, I am glad I got this worked out. Hopefully this will sameone else some time and grief!
Thank for this very cool gem Ryan!
adding support for loading through Inherited Resources - closed by 4eee637
If someone wants to try this out the latest commit that would be great. You need to do load_and_authorize_resource and the loading should now happen through Inherited Resources when that is available. The reason you can't just do authorize_resource is because InheritedResources does lazy loading. Also because CanCan does some additional loading functionality such as the accessible_by on the index action.
Hey Ryan, thanks a lot for coding it. I'll try to test it out in the weekend.
Hi Ryan, I ran into some issues (in before filter the filter was still using ControllerResource instead of .cancan_resource_class, and the methods #resource, and #build_resource are protected in ::InheritedResources::BaseHelpers)
So I made those little changes in my branch (sorry, no tests though :( )
BTW, it's the first time I use cancan and I liked it :)
Thanks for pointing these problems out, I'll merge them in.
With these changes for InheritedResources, should we have to override the collection and resource methods to use accessible_by?
@contentfree, Nope, it should do it automatically as long as load_resource is in the controller.
Very right, sir. Thanks.
I am currently having issue described above with belongs_to and load_and_authorize_resource.
Is this fixed?
I use it as follows:
belongs_to :business_unit, :optional => true
@bmihelac, you need to load_and_authorize_resource for the business_unit too, I believe. Should probably look something like the following:
belongs_to :business_unit, :optional => true
load_and_authorize_resource :your_resource_name, :through => :business_unit
oh yes, that works. thanks @contentfree