Cancan question - create rule issue

Hi, RoR newbie here. Fairly new, anyway. :). I have a cancan question I'm hoping someone can help me with. I have two models - ProposalRequest and Proposal. Each ProposalRequest can have many Proposals, but a given user can submit only one Proposal for each ProposalRequest. I can't figure out how to define the rule in ability.rb for the create action. Can someone help?

Thanks

Stan McFarland

Hi Stan,

Try something like this

def initialize(user, proposal_request_id)

can :create, Proposal unless Proposal.exists?(:proposal_request_id => proposal_request_id, :user_id => user.id)

end

I assume you would need to know if

proposal_request.proposals.collect { |p| p.user_id }.include? user.id

so maybe you want something in the ProposalRequest like

def proposed?(user)
proposals.collect { |p| p.user_id }.include? user.id
end

Now I assume that upon creating a Proposal, it already has a belongs_to relation with the current PorposalRequest, but I am not quite sure of it.
can :create, Proposal |proposal| do
proposal.proposal_request.proposed? user
end

Cheers
ace

Hmmm… this kinda makes sense to me, only it didn’t work. The proposed? method works correctly, but the can? method in my template returns true for both proposed and non-proposed ProposalRequests. I’m having a hard time getting my head around validating a Proposal against it’s parent when the Proposal hasn’t even been created yet.

Thanks,

Stan

Exactly. The Proposal hasn’t been created, but you want to create a proposal for a certain proposal request. That PropsalRequest must already exist, right? Don’t know how to get that into the ability model, maybe like Max did and include it in the init method?

ace

I'll try. I'm not familiar with passing additional parameters to the initialize method but I'll give it a shot. Thanks for both of your help.

Stan

It might be easier to do it with a validation rather than cancan, or
would that not do what you want?

Colin

I Think a validation will only work after data is entered. With authorization (as in CanCan) the possibility of creating a new proposal can be avoided all together.

I did some experiments but yes, it’s possible to put extra arguments into the initialize method.

For instance, initialize(user, project_proposal=nil).

In case you want to check you could use
ability=Ability.new(user,project_proposal)
ability.can? :create, :proposal

should give you a true or false based on what project_proposal was entered.

Ace