Nested Resource Check Creates Temporary Object #608

Closed
alininja opened this Issue Apr 24, 2012 · 7 comments

Projects

None yet

3 participants

@alininja

Hi,

Thanks for creating such an awesome Gem!

So I've read your wiki on testing nested resources: https://github.com/ryanb/cancan/wiki/Nested-Resources

And I'm trying to implement something like this:

if can? :create, @project.tasks.build

In my case it would be:

if can? :create, @list.items.build

since I have:

project has_many lists
list has_many items

After this test, I list out all the items of the list, basically showing all the items for a particular list. But since the code performed a build (from what I can tell, it's behaving the same like new and create), the extra empty item object is listed in the show.

So the table looks l like:

Task Title  Due Date    Percent Complete    Edit
Item 1-A-1  2012-02-02  10%     Delete
Item 1-A-2  2012-02-03  20%     Delete
/items/edit         

That extra line on the bottom is what I'm trying to get rid of. I hope I'm making sense.

I was able to get rid of it using something like:

can?(:create,@list.project.lists.create)

since access to item/list is determined by whether or not the user has access to the project. But this feels like a hack, and the test is testing lists and not items.

The other alternative is to un-"build" the temporary object, but I'm having issues Googling how to do that.

Is there a recommended method of accomplishing the :create test without generating an extra object?

I'm also not quite sure this is an issue, but can't find anywhere else to ask this question. Sorry, if this is in the wrong place.

Thanks for your time!

Update: Formatted the issue description. (12 May 2012)

@andhapp
Collaborator

@alininja: I see you mentioned that access to item/list is determined via project, but can you please post the defined abilities.

Also, won't something like this work:

if can? :manage, Project 
  @list.items.build
end

Apologies, but I'm not familiar with your project and this might seem totally absurd.

@andhapp andhapp was assigned May 13, 2012
@andhapp
Collaborator

I am going to close this ticket for now. Please comment here if you are still having this issue and it will be reopened.

@andhapp andhapp closed this May 17, 2012
@alininja

class Ability
include CanCan::Ability

def initialize(user)
@user = user || User.new # guest user (not logged in)

if user
  can :create, Project

  if user.lead_account
    can [:manage,:create], [Project,List,Item] do |resource|
      resource.accessible_by_lead_account?(user.lead_account)
    end
  end
  if user.support_account
    can [:read, :update], [Project,List,Item] do |resource|
      resource.accessible_by_support_account?(user.support_account)
    end
  end

else
  can :read, Project
end

end
end

@alininja

Hi andhapp,

Sorry for the delay in responding to you. I've attached the ability.rb above.

Yes, most definitely I could use something like what you posted:
if can? :manage, Project
@list.items.build
end

However, I want to test the ability to create an item directly. It just seems more simple and will be less confusing later on should the rules change.

I'm just wondering if there's a simple way to test for the ability to create an item, without making a temporary object that gets displayed. Or maybe there's a way to destroy temporary objects before displaying the results? The latter option still feels like hack and isn't as simple and direct as I would like.

Anyways, thanks for your help. I'm new to Rails and Ruby and CanCan, so I was just wondering if there's a simple command out there that I'm missing.

If not, then most definitely I can use the solution you proposed. Or just test it like this:
can?(:create, @list.project.lists.create)

But again, I'm not testing on creating an item directly and am just using the structure of the abilities as a work around. Just looking for something more simple and direct.

If it doesn't exist, then no biggie. As long as I'm not missing something simple.

Thanks!

@andhapp
Collaborator

@alininja: If you read the documentation for nested resources, it implies that when one is building a "task" through a "project", i.e. in the create action. In your case, you are checking for the same but, I guess, in the show action.

@alininja

Hi andhapp,

Thanks again for helping me with this.

So it sounds like from the documentation, that something similar to:
<% if can? :create, @project.tasks.build %>
is what we are suppose to use.

It just happens that using that in the show action has an unfortunate side effect.

Okay, now I know. I'll just have to work around it, maybe using one of your solutions proposed above.

Thanks again for your time!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment