11

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

<%= current_user.welcome_message %>

代替

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

但问题是你必须在代码中的某处有决策逻辑。

我的理解是做出决定templatecontroller让你的控制器更干净更好。这是正确的吗?

有没有更好的方法来处理这个?

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

4

10 回答 10

11

你不是第一个对此感到疑惑的人。如果视图和控制器应该几乎没有逻辑,并且模型应该与表示无关,那么表示逻辑属于哪里?

事实证明,我们可以使用一种称为装饰器模式的旧技术。这个想法是用另一个包含你的表示逻辑的类来包装你的模型对象。这个包装类称为装饰器。装饰器从您的视图中抽象出逻辑,同时使您的模型与其表示隔离。

Draper是一个优秀的 gem,可以帮助定义装饰器。

您提供的示例代码可以这样抽象:

@user = UserDecorator.new current_user在控制器中将装饰器传递给视图。

您的装饰器可能如下所示。

class UserDecorator
  decorates :user

  def welcome_message
    if user.admin?
      "Welcome back, boss"
    else
      "Welcome, #{user.first_name}"
    end
  end
end

你的观点只会包含@user.welcome_message

请注意,模型本身不包含创建消息的逻辑。相反,装饰器包装模型并将模型数据转换为可呈现的形式。

希望这可以帮助!

于 2012-08-02T05:50:30.990 回答
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) %>

请注意,装饰器/演示器提供了一种非常干净的面向对象的方法,但是恕我直言,使用助手要简单得多且足够。

于 2012-08-02T13:52:40.563 回答
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
于 2012-07-29T12:57:36.417 回答
3

装饰用户模型并将welcome_message直接添加到其中。是的,这可能在某些时候涉及某种条件语句。

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

于 2012-07-29T12:19:04.597 回答
1

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

于 2012-07-27T04:20:18.547 回答
1

我认为您应该观看 Presenters 上的 railscasts 剧集来寻找答案。

于 2012-07-30T09:15:27.950 回答
1

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

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

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

于 2012-08-02T10:21:34.407 回答
0

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

另一种选择是定义一个自定义帮助模块,它不一定与给定的视图或控制器相关联(请参阅下面链接的视频),并且include它位于您希望具有该功能的视图/控制器的模块中。

这不是非黑即白的。但是,根据您的描述,这听起来像是在您的 application_controller.rb 中插入的代码,并且它不是具有证明其自己控制器合理性的功能的代码,最有效和最有效的选择可能是创建自定义帮助模块并将其包含在您希望拥有该功能的助手中。也就是说,这最终是应用程序的设计者(即)需要决定的判断调用。

是一篇很好的文章,概述了2011 年 5 月的帮助模块

是一个 RailsCast 概述自定义帮助模块(即自定义模块不一定与给定的控制器或视图相关联)。简短,甜蜜,切中要害。

于 2012-07-29T12:08:07.667 回答
0

您可以为这些东西定义辅助方法。我认为在模型中制作欢迎句子不是一个好主意,但在控制器中也是如此。但是您应该尝试使您的视图从代码中干净,如果您可以为此使用帮助程序,那么您应该这样做。

于 2012-08-01T19:13:32.763 回答
0

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

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

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

于 2012-08-03T23:47:37.700 回答