Rails Routes - 动态选择控制器

时间:2013-07-05 16:08:51

标签: ruby-on-rails ruby routes

让我们说,为了这个问题,我有两种用户类型:type1& type2。我希望Rails使用控制器/模块,具体取决于所显示的用户类型。例如:

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

/users/1

将选择Type1 :: UsersController。然后去:

/users/2

将选择Type2 :: UsersController。

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

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

2 个答案:

答案 0 :(得分:2)

正如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进行单表继承)。我已经对此进行了测试,并且可以根据需要运行。

答案 1 :(得分:0)

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

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

那就是说,一条更好的路线(没有双关语)将是一个控制器,它有一个可以选择视图的集中方法。

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

因此,调用find_view('new')将尝试呈现名为“new-type1”的视图。您可以将所有type1特定于用户的逻辑放在该视图中。用户类型2相同。

同样,因为我认为您的用户代码会有很多重叠,您可能希望将此find_view方法推送到帮助程序类,以便您可以从视图中调用它,并执行类似渲染特定部分的操作用户类型。这将允许更多的代码重用,这从来都不是坏事。

一旦你掌握了一个控制器,你可以通过一些简单的方法将用户类型特定的代码推送到不同的途径 - 上面介绍的视图方法,你可以推送所有相关的代码根据用户类型分离动态调用的助手,我确信还有更多(可能更好的)。但是所有这些都有一个共同的重点 - 你将更少地与Rails战斗,如果你屈服于让Rails通过一条路线,一个控制器,那么你将拥有更少的重复代码。

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