1

我有一个自定义路由设置,在 url 中有一个 location_id(见下文)

resources :menu_items, :path => "/location_menu/:location_id"

所以当我点击/location_menu/1它时,它会显示 location_1 的菜单,/location_menu/2会显示 location_2 的菜单,等等。

每个用户都关联到多个位置 ( has_many :locations)

我正在尝试使用 cancan 来限制用户查看某些 menu_item URL。

例如:用户 1 与位置 1 和 2 相关联。因此他们只能查看页面/location_menu/1/location_menu/2。但他们将无法查看/location_menu/3

我在控制器中创建了一个自定义方法作为 before_filter :

before_filter :location_check
 ... 
def location_check
  @location = Location.find(params[:location_id])
  authorize! :see_location, @location
end

以我的能力.rb

can :see_location, MenuItem do |location| location && user.location_ids.include?(location.id) end

出于某种原因,这对我不起作用。我可能做错了什么?如果你们能帮助我,我将不胜感激!

谢谢。

4

2 回答 2

1

在ability.rb中检查一次,

user.location_ids.each do |l|
  can :view, MenuItem, location_id: l
end
于 2013-07-30T12:44:30.437 回答
0

首先,我没有看到您从定义自定义路由而不是嵌套资源中获得什么好处,但它看起来像是在夸大您的域语言并导致任何特定资源可以由多个不同名称引用的情况 -这可能会变得足够混乱,以至于现在值得简化。

在您的方法中,您正在对一个实例location_check进行授权,但是您向我们展示的类的部分涉及一个类。试着像这样定义你的能力:see_locationLocationAbilityMenuItem

can :see_location, Location, id: user.location_ids

编辑

如果你需要一个 cancan 动作来MenuItems直接授权,试试这个(假设belongs_to :location关系 on MenuItem):

can :view, MenuItem, location_id: user.location_ids

至于你的路线,想得更简单。你只需要这样:

resources :location_menus

...然后与此相关的所有内容都放入LocationMenusController. 不要担心没有同名的模型 - 您仍然可以使用 查找您的位置Location.find(params[:id])。据我了解,位置菜单页面的所有内容都取决于当前用户对特定位置的访问,因此您可以将LocationMenu其视为一种虚拟资源Location

于 2013-05-06T16:34:33.377 回答