ruby on rails-DRY一大块具有两种截然不同用途的公共代码



我有一个"小部件",它包含一个html/css代码块。这是一种数据布局,我称之为"堆栈"

堆栈中嵌入了一些.erb(RubyonRails),它为每个用户输入数据。

我需要在多个地方包括这个堆栈,它需要表示来自不同模型的不同数据

因此,一个堆栈可能包含一个名为@company.name的字段,而另一个堆栈则可能包含@project.name || "Unidentified Project"

如何重构/组织这种情况?我可以看到的选项:

  1. 有两个单独的stacks,这将引入冗余和不一致性,但这将是一个明显的问题答案,而不限于特定场景的定制
  2. 为每个数据点包含if语句,以测试堆栈用于何种环境,但对于2个以上的堆栈来说,这是非常糟糕的代码,而且非常复杂
  3. 一些未知的未知

你将如何解决这个问题?

一个简单的方法是以通用的方式编写erb,使其适用于项目或公司。例如,在您的项目模型中,您可以放置:

def display_name
  name || "Unidentified Project"
end

然后在您的公司模型中放入:

def display_name
  name
end

当您呈现ERB时,传入一个具有某种通用名称(如main_object)的变量,并调用其display_name函数。ERB代码不知道或不关心main_object是什么类:

<%= main_object.display_name %>

如果在模型中放置与显示相关的函数(如display_name)会让您感到困扰,则可以使用Presenter模式。礼物基本上是一个普通的旧ruby对象,您可以从模型中创建它,然后将它传递给视图。我看过Jeff Casimir关于这种模式的一篇很好的演讲,名为"胖模特不够用",幻灯片如下:http://en.oreilly.com/rails2011/public/schedule/detail/18514

David的解决方案很好。在某些情况下,您还可以考虑助手或部分(例如,如果您想包含复杂的html)。例如:

助手

def display_name(object)
  if object.respond_to? :name and object.name
    object.name
  else
    if object.class.respond_to? :human_name
      "Unidentified #{object.class.human_name}"
    else
      "Unidentified #{object.class.name}"
    end
  end
end

部分

<%= render :partial => "stack/name/#{object.class.underscore}", :locals => {object.class.underscore => object} %>

app/views/stack/name/_project.html.erb:中任何复杂ERB

<label style="<%= "background-color: red;" if project.name.blank? %>">
  <%= project.name || "Unidentified Project" %>
</label>

相关内容

  • 没有找到相关文章

最新更新