,所以我有一些轨道型号。这是一个类似的示例列表:
- 一所房子属于一个社区
- 一个社区属于一个城市
- 一个城市属于一个国家
- 一个国家属于一个国家
- 一个用户属于房屋
我想获得一个非常神奇的功能,我可以使用如下:
(resource, scope, scope_ids) => {...}
成功的电话看起来像:
("house", "country", [30]) => { neighborhood: { city: { state: { country: [30] } } } }
("house", "state", [1,2,3]) => { neighborhood: { city: { state: [1,2,3] } } }
和一个失败的呼叫将返回:
("house", "people", [1,2,3]) => { id: -1 }
我想自动进行此操作,以便任何经过硬编码的东西都是不可接受的。
编辑:
我想实现上述结果,因为我正在使用cancancan开发授权层,允许做以下事情:
can :read, House, { neighborhood: { city: { state: { name: "Illinois" }}}}
考虑了上述语法,我想自动产生权限,例如(例如," ownoughtorhood"是被授权的用户的内居性,而" ershots_houses"与被授权的用户的房屋不同(:
# permission read_own_neighborhood_houses should generate:
can :read, House, { neighborhood: { users: {id: user.id } }
# permission read_own_state_cities should generate:
can :read, City, { state: { cities: { houses: { users: {id: user.id } } } } } } }
# permission read_others_neighborhoods_states should generate:
can :read, State, { cities: { neighborhoods: { houses: { users: { id: User.where.not(id: user.id) } } } } }
这当然需要大量的元编程。这可能是使用reflections_on_all_associations
方法的开始...
给定permission read_own_state_cities
def permission(perms)
@perms = perms.split('_') #['read', 'own', 'state', 'cities']
@model = @perms[-1].singularize.capitalize.constantize #City
@action = @perms[0].to_sym #:read
@ownership = @perms[1].to_sym #:own
@top_level = @perms[2] #:state
hash_items = []
current_level = @top_level
until current_level = :user do
hash_items << current_level
current_level = current_level.reflect_on_all_associations(:has_many).first.name.to_sym
end #[:state, :cities, :neighborhoods]
@hash = hash_items.reverse.inject({users: {}}) { |a, n| { n => a } } #{state: {cities: {neigborhoods: {users: {}}}}}
end
这是我很容易获得的,而没有您的实际情况进行测试。您需要根据@ownership
的值来解决如何确定users: {}
哈希的内容。这应该为您提供最终即时建立can....
所需的一切。