将表示逻辑放在控制器中是Ruby的一个好习惯吗?

时间:2012-07-27 04:14:06

标签: ruby-on-rails ruby templates presentation-layer

有些建议[1]建议您使用

<%= current_user.welcome_message %>

而不是

<% if current_user.admin? %>
  <%= current_user.admin_welcome_message %>
<% else %>
  <%= current_user.user_welcome_message %>
<% end %>

但问题是你必须在代码中的某个地方拥有决策逻辑。

我的理解是让template中的决定优于controller因为它会使您的控制器更加干净。这是对的吗?

有没有更好的方法来解决这个问题?

http://robots.thoughtbot.com/post/27572137956/tell-dont-ask

9 个答案:

答案 0 :(得分:5)

我会为此使用帮助器。假设您必须根据某些区域设置翻译欢迎消息。

app/helper/user_helper.rb

module UserHelper

  def welcome_message(user)
    if user.admin?
      I18n.t("admin_welcome_message", :name => user.name)
    else
      I18n.t("user_welcome_message", :name => user.name)
    end
  end 

end

然后在您的视图中,您可以编写

<%= welcome_message(user) %>

请注意,装饰器/演示者提供了一种非常干净的面向对象的方法,但使用帮助器的imho更加简单和充分。

答案 1 :(得分:4)

不,您不希望用户类和控制器中的任何条件。博客文章中的那个例子的要点是引用多态,只是老式的OO设计。

# in application_controller for example
def current_user
  if signed_in?
    User.find(session[:user_id])
  else
    Guest.new
  end  
end

#app/models/user.rb
class User
   def welcome_message
     "hello #{name}"
   end
end

#app/models/guest.rb
class Guest
  def welcome_message
    "welcome newcomer"
  end
end

......你明白了。

只有创建一个充当演示者的装饰器,而不是使用仅演示方法乱丢你的模型:

require 'delegate'
class UserPresenter < SimpleDelegator
  def welcome_message
    "hello #{name}"
  end
end

现在current_user看起来像这样:

# application_controller
def current_user
  if signed_in?
    UserPresenter.new(User.find(session[:user_id]))
  else
    Guest.new
  end
end

答案 2 :(得分:3)

装饰用户模型并直接向其添加welcome_message。是的,这可能在某些时候涉及某种条件陈述。

http://robots.thoughtbot.com/post/14825364877/evaluating-alternative-decorator-implementations-in

答案 3 :(得分:1)

在我看来,如果文本是唯一改变的东西,它就不属于视图。如果您需要重新构建页面,那就是表示逻辑。这,这只是数据不同。

答案 4 :(得分:1)

我认为你应该在Presenters上观看有关的轨道广播剧集。

答案 5 :(得分:1)

视图中的逻辑难以维护,我们应该将业务逻辑放在模型中,将所有视图逻辑放在帮助器中。

如果您希望您的代码采用面向对象的方式,请使用装饰器(面向对象的帮助方式)

最佳示例:https://github.com/jcasimir/draper

答案 6 :(得分:0)

将定义current_user.welcome_message的代码放在_app / helpers / application_helper.rb_中,然后可以通过使用应用程序布局呈现的任何视图访问它。

另一种选择是定义一个自定义辅助模块,一个不一定与给定视图或控制器相关联(参见下面链接的视频),以及include您希望在其中具有该功能的视图/控制器的模块。

这不是黑白的东西。但是,从你所描述的内容来看,这听起来像是一个突兀的代码,坚持你的application_controller.rb并且它不是具有证明它自己的控制器的功能的代码,最有效和最有效的选择可能是创建一个自定义帮助器模块并将其包含在您希望具有该功能的帮助程序中。也就是说,这最终是一个判断调用,应用程序的设计者(即)需要决定。

Here是一篇很好的文章,概述了来自 2011年5月的辅助模块

Here是一个概述自定义辅助模块的RailsCast(即自定义为模块,不一定与给定的控制器或视图相关联)。简短,甜蜜,至关重要。

答案 7 :(得分:0)

您可以为该东西定义辅助方法。我不认为在模型中制作欢迎句子是一个好主意,但在控制器中也是如此。但你应该尝试通过代码让你看清楚,如果你可以使用帮助,那么你应该这样做。

答案 8 :(得分:0)

一个好的做法是拥有真正的View个实例。不幸的是,Rails模仿MVP(有区别,查找它)似乎假装视图是模板。那是错的。

视图应该包含MVC和MVC启发模式中的表示逻辑。他们还应该操纵多个模板,并决定使用哪些模板来表示模型层的状态和信息(是的,模型是一个层而不是ORM实例)。

所以,回答这个问题:表示逻辑在控制器中没有位置。