4

I have the following:

  • User model that has_and_belongs_to_many Restaurants and vice-versa.
  • Restaurant model that has_and_belongs_to_many Meals and vice-versa.

In my ability.rb file, I want to specify that a user can only manage meals of restaurants he "has_and_belongs_to" (i.e. restaurants in user.restaurants).

I have this right now:

class Ability
  include CanCan::Ability
  def initialize(user)
    # a user can only manage meals of restaurants he has access to
    can :manage, Meal do |meal| 
      meal.restaurant_ids & user.restaurant_ids #...this doesn't work...
    end
  end
end

What's the best way to do this?

I've consulted https://github.com/ryanb/cancan/wiki/Defining-Abilities-with-Blocks but I still don't know.

James Chevalier
  • 10,604
  • 5
  • 48
  • 74
dmonopoly
  • 3,251
  • 5
  • 34
  • 49

1 Answers1

7

The "&" operator on an array will always return an array. An empty array is not considered false, so it will always pass. Try checking if it is present (not blank).

(meal.restaurant_ids & user.restaurant_ids).present?
ryanb
  • 16,227
  • 5
  • 51
  • 46
  • Neat - thanks for responding. I'll try this out soon. Out of curiosity, where is this present?() method defined? It's not in Ruby Array's doc... – dmonopoly Jul 26 '11 at 17:05
  • ah found it here.... http://api.rubyonrails.org/classes/Object.html#method-i-present-3F :] – dmonopoly Jul 30 '11 at 02:23
  • Sorry for commenting on an old question. If I am doing the `:create` action on a form and I'm check-boxing which restaurants the meal belongs to, is it possible for me to spoof the system by sending in 1 restaurant ID that is owned by me and 1 that isn't? The condition above will return true because one correct ID is present. – Damon Aw Mar 02 '12 at 09:36