Rails Routes-动态选择控制器



为了这个问题,我们假设我有两种用户类型:type1&CCD_ 2。我希望Rails根据显示的用户类型使用控制器/模块。例如:

如果User(id: 1, type: 'type1')type1User(id: 2, type: 'type2')type2,则转到:

/users/1

将选择Type1::UsersController。去:

/users/2

将选择Type2::UsersController。

这将允许我为每种类型使用不同的控制器和视图。

注意:我不希望type显示在URL中,我希望它是动态的。

正如GoGoCarl所说,这并不是Rails真正的做事方式。也就是说,让它发挥作用并不难。您可以在routes.rb:中执行类似操作

get 'users/:id', to: 'type1/users#show', constraints: lambda { |request| 
  _id = request.fullpath.gsub('/users/','').to_i
  # Note: there might be an easier way to get ID from the request object
  User.find(_id)._type == 'type1'
}
get 'users/:id', to: 'type2/users#show', constraints: lambda { |request| 
  _id = request.fullpath.gsub('/users/','').to_i
  User.find(_id)._type == 'type2'
}

在我的示例中,我已经将type字段重命名为_type(因为Rails使用type进行单表继承)。我已经测试过了,它按要求工作。

这是可能的,但你会做很多(可能)不必要的对抗Rails的方式。我想你会想要一个控制器,因为可能有相当多的共享逻辑(如保存、删除、创建等)。

要回答你的问题(因为我讨厌人们留下推荐而不是答案),那么你需要创建一个扩展路由的模块,它将允许你进行自定义匹配。从那里,你可以进行适当的检查和路线。下面是一个例子。

也就是说,一个更好的方法(并非双关语)是有一个控制器,该控制器具有可以选择视图的集中方法。

def find_view view_name
  "#{view_name}#{@user.type}"
end

因此,调用render find_view('new')将尝试渲染名为"new-type1"的视图。您可以在该视图中放入所有类型1用户特定的逻辑。用户类型2也是如此。

同样,由于我认为您的用户代码中会有很多重叠,您可能需要将这个find_view方法推送到一个helper类中,这样您就可以从视图中调用它,并根据用户类型来渲染特定的部分。这将允许更多的代码重用,这从来都不是一件坏事。

一旦你开始考虑拥有一个控制器,有很多简单的方法可以将特定于用户类型的代码推送到不同的途径——上面解释的视图方法,你可以将所有相关的代码推送给单独的助手,这些助手是根据用户类型动态调用的,我相信还有更多(可能更好)。但所有这些都有一个主要的共同点——如果你屈服于让Rails拥有一个路由,一个控制器,那么你与Rails的斗争就会减少很多,重复代码也会减少。

祝你好运,希望能有所帮助。

最新更新