'告诉,不要问'同时保持关注点分离

时间:2014-09-23 10:27:59

标签: ruby-on-rails ruby separation-of-concerns

在我的Rails应用程序中,我有以下关联:

  • 视频属于流派 (视频无需播放)
  • 流派有很多视频 (流派可以没有视频)

在视频模型中,我有以下方法。

# models/video.rb
def genre_name
    genre.present? ? genre.name : ''
end

这是为了在视图中避免这样的事情(这看起来很混乱):

# views/videos/show.html.erb
<% if @video.genre.present? %>
    <%= @video.genre.name %>
<% else %>
    No Genre Present
<% end %>

相反,我可以这样做(看起来更整洁)

# views/videos/show.html.erb
<%= @video.genre_name %>

然而,在视频模型中询问有关类型的信息并不合适。组织此代码的最佳方法是什么?我应该使用帮手吗?

2 个答案:

答案 0 :(得分:2)

您可以在视图中写下

<%= @video.genre.try(:name) || 'No Genre Present' %>

如果您不需要后备文字,只需

<%= @video.genre.try(:name) %>

Read more about Object#try here

如果您希望在name为空字符串(而不仅仅是nil)时进行后备,则可以使用Object#presence

<%= @video.genre.try(:name).presence || 'No Genre Present' %>

答案 1 :(得分:2)

如果你发现自己做了很多这样的事情,可能值得研究装饰模式,它可以容纳这样的视图逻辑。 (我非常喜欢使用Draper来实现此目的,但是推出自己的天真实现并不是很困难。)

然后,您的装饰器逻辑可能如下所示:

class VideoDecorator
  def genre_name
    object.genre.try(:name).presence || "Fallback"
  end
end

您可以在控制器中渲染时在装饰器中包装模型:

@video = Video.find(params[:id])
respond_with @video.decorate

你的观点'逻辑'(或缺乏)可能看起来像这个应用程序范围:

<%= @video.genre_name %>

Thoughtbot对装饰器模式here

有很好的解释