【问题标题】:Rails - should link text be set in controller or view?Rails - 应该在控制器或视图中设置链接文本吗?
【发布时间】:2020-05-02 07:46:48
【问题描述】:

我正在与控制器中应该有多少逻辑以及视图中应该有多少逻辑作斗争?

例如,我有一个“切换”链接,可以打开和关闭过滤器。结果是带有一些文本的链接,具体取决于切换的状态以及是否添加了查询参数。

即一种状态

<%= link_to 'With filter', polymorphic_path(Thing, { filtered: 1 }) %>

其他状态

<%= link_to 'Without filter', polymorphic_path(Thing, {}) %>

我在控制器中分配链接标签和查询参数之间犹豫不决,所以我将在视图中没有逻辑,并且两个变量都在控制器中设置...

<%= link_to @filter_link_text, polymorphic_path(Thing, @filter_link_params) %>

但似乎我在控制器中放入了太多视图逻辑

或者控制器设置一个简单的标志并将其余部分留给视图......

<% if @offer_filter %>
  <%= link_to 'With filter', polymorphic_path(Thing, { filtered: 1 }) %>
<% else %>
  <%= link_to 'Without filter', polymorphic_path(Thing, {}) %>
<% end %>

翻译有帮助吗?

谢谢。

【问题讨论】:

  • @filter_link_params 的值取决于什么?
  • @SebastianPalma 这是一个切换 - 如果控制器看到它设置在 params 中,那么 @filter_link_params 将为空。如果params 为空,则设置@filter_link_params
  • 我可能会在这里回答我自己的问题,不过……如果以后我决定重构 UI 以使其不再是链接怎么办。我可能会添加另一个过滤器,然后可能会添加一组带有整体“过滤器”按钮的复选框?这都应该与视图相关。也许控制器应该做的就是将过滤器的当前状态传递给视图?
  • 什么是Thing?类还是对象?
  • @Schwern Thing 是一个模型类。我知道我可以使用things_path,但我想让这个示例保持简单,我的实际代码有嵌套资源,polymorphic_path 更容易使用

标签: ruby-on-rails model-view-controller


【解决方案1】:

你有很多选择,这取决于具体情况。

想将视图文本放入控制器。没有@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' %>

中间立场是使用decorator。装饰器是模型周围的薄包装器,可让您添加和更改特定于特定用途的行为。它避免了用一堆视图代码使模型变胖。

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 和装饰器开辟了更多的方法来保持您的视图逻辑良好的因素,并防止它膨胀您的控制器和模型。

【讨论】:

  • Partials 并不是很难单独测试。您只需使用ActionView::TestCase 或 RSpec 中的视图规范并传入本地变量,然后编写有关生成的 HTML 的断言。诚然,我不经常写它们,因为我试图用功能规范覆盖视图并降低复杂性。
  • 谢谢@Schwern。实际上,我可能没有完全解释自己过滤器的重点是限制控制器中的索引范围,而不是单个实例。我同意你关于部分的观点 - 是的,我一定会这样做。
猜你喜欢
  • 1970-01-01
  • 2013-01-06
  • 1970-01-01
  • 2013-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-18
  • 1970-01-01
相关资源
最近更新 更多