在这种情况下诉诸send()是一种好习惯吗?

时间:2015-10-11 04:08:18

标签: ruby-on-rails ruby ruby-on-rails-4

我有一个应用程序布局,其中包含登录用户编辑其个人资料的链接。最初是这样的:

<%= link_to "Settings", edit_user_path(current_user) %>

但后来我需要不同类型的用户,我最终得到了这个:

<%= link_to "Settings", send("edit_#{current_user.type.downcase}_path", current_user) %>

Users表上的“type”列用于STI,我可以神奇地拥有User(Model)类的子类,这对我来说非常方便。

我也有UsersController的子类,所以我会为每种类型提供“edit_ TYPE _path”路径。

有更好的方法可以做到这一点,还是我做得很好?

2 个答案:

答案 0 :(得分:2)

polymorphic网址助手可以在这里完成工作:

edit_polymorphic_path(current_user)

应该做的伎俩。如果您确实发现自己需要使用send,那么(如果可能)请尝试使用public_send。顾名思义,这只会调用公共方法。

旁注type.downcase不太正确 - 如果类名是FooBar,那么路由名称将是edit_foo_bar_path而不是edit_foobar_pathunderscore变形更接近您的需求

答案 1 :(得分:0)

polymorphic path建议就是您所需要的。

您也可以使用eval -

eval("edit_#{current_user.type.downcase"}_path(#{current_user.id})")

......虽然显然polymorphic_path更受欢迎。

由于系统的结构,我觉得答案是合适的(这在评论中被选中)。

STI的东西很棒 - 我觉得它不应该像我们应该的那样。但是,关于编辑您的个人资料,我认为您不需要每次都更改控制器操作。

当然,你可能,如果你这样做,那么我想你知道你在做什么。

但是,如果是我,我会将它全部保存在users控制器中,即使你有不同的路径可以到达那里。如果需要,您可以随时将功能推断为助手等:

#config/routes.rb
resources :users, only: [:edit, :update], path: "", path_names: {edit: "profile", update: "profile" }

这将产生以下网址:

# GET   url.com/profile
# PATCH url.com/profile

现在...

这里重要的是这句话:

  

修改 他们的 个人资料

这是每个用户的基础。

如果您需要不同的功能,则必须使用单独的控制器,但由于您总是会引导用户他们的配置文件,我认为您不需要不过是一个控制器。

你可以做这样的事情:

#app/models/user.rb
class User < ActiveRecord::Base
   def is? is_type
      type == is_type
   end
end

#app/controllers/users_controller.rb
class UsersController < ApplicationController
   def edit
      current_user.is?(:admin) ? change_admin : change_user
   end

   private

   change_admin
      #logic
   end

   change_user
      #logic
   end
end

这假设您的用户在功能上非常相似。