你有很多选择,这取决于具体情况。
您不想将视图文本放入控制器中。没有@filter_link_text
。控制器将模型连接到视图。视图处理事物的显示方式。
最简单的是您已经建议的,控制器设置视图使用的标志。
<% if @offer_filter %>
<%= link_to 'With filter', polymorphic_path(@thing, { filtered: 1 }) %>
<% else %>
<%= link_to 'Without filter', polymorphic_path(@thing, {}) %>
<% end %>
然后你可以把它移到一个partial中。将代码移入app/views/shared/_filtered_thing.html.erb
并在您的视图中呈现。这简化了您的视图并允许共享视图代码。
<%= render 'shared/filtered_thing' %>
中间立场是使用装饰器。装饰器是模型周围的薄包装器,可让您添加和更改其特定于特定用途的行为。它避免了用一堆视图代码使模型变胖。
draper
实现装饰器并与 Rails 很好地结合。它使用了一个非常相似的问题作为示例。
class ThingDecorator < Draper::Decorator
delegate_all
def filter_toggle_link(filtered)
if filtered
# h allows access to the Rails helper methods
h.link_to 'With filter', h.polymorphic_path(self, { filtered: 1 })
else
h.link_to 'Without filter', h.polymorphic_path(self, {})
end
end
end
现在,您的视图在装饰对象上调用该方法。
<%= @thing.filter_toggle_link(@offer_filter) %>
您还可以为您的装饰器添加标志。例如,如果您需要为每个对象设置过滤。
class ThingDecorator < Draper::Decorator
delegate_all
attr_accessor :filtered
def filter_toggle_link
if filtered?
# h allows access to the Rails helper methods
h.link_to 'With filter', h.polymorphic_path(self, { filtered: 1 })
else
h.link_to 'Without filter', h.polymorphic_path(self, {})
end
end
def filtered?
filtered
end
end
# In the controller
@thing.filtered = true
# In the view
<%= @thing.filter_toggle_link %>
与局部视图相比,装饰器的一大优势是您可以对装饰器进行单元测试。
Partials 和 decorators 开辟了更多的方法来保持你的视图逻辑很好地分解并防止它膨胀你的控制器和模型。