collection_select 中自定义 text_method 的最佳实践?

Best practice for custom text_method in collection_select?

我有 Rails 应用程序,其中包含一个在 collection_select 下拉框中显示价格的用例。例如,产品名称及其价格,或客户和欠款额。

我很清楚,简单地包含相关的帮助程序来访问像 number_to_currency 这样的函数是不好的 MVC 做法,但是我对 Product 或 Payment 模型的自定义方法所能做的最好的事情就是获取一个值看起来像 20.2 美元。因此,它是可读的,但不是最理想的,因为系统的大多数用户都希望将 20 美元和 20 美分表示为 20.20 美元。

有人对轻松自定义 collection_select 的 text_method 有什么建议吗?

放弃使用 collection_select 方法,只使用 select 在您看来:

<% options = @payments.each { |p| number_to_currency(p.price), p.id } %>
<%= f.select :payment, options %>

因为您在视图中,所以您期望的一切都在那里,包括模型和辅助方法。

我对你的 HTML 做了假设,因为你没有给出具体的例子,但我认为上面的代码块是你需要开始的一切。更多详情:http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-select

如果您与 collection_select 结婚,您可以随时推出自己的货币数字格式化程序;纯 Ruby 应该不难。但是,上面的方法在长期 运行 中会更强大,并为您提供更多的帮助选项,并让您在视图中一致地使用函数。

text_method 以及 collection_select 中的 value_method 接受符号,但也接受 a lambda/proc 块 获取当前集合元素作为参数。请参阅文档 here。 lambda 在视图的上下文中执行,因此所有视图助手都应该在其中可用。

因此,要获得由货币格式化程序格式化的模型价格,您应该能够像下面这样调用 collection_select

<%= collection_select :user, :payment_id, @user.payments, 
                     :id, ->(pmt) { number_to_currency(pmt.amount) } %>

您没有显示您的模型关联,因此这只是一个用户有很多付款的示例,您希望在 select 框文本中为其设置价格格式。

我最终根据 GoGoCarl 的建议进行了构建,但将数组生成移至助手:

module PaymentsHelper
  def invoices_for_payment_select(invoice)
    @invoices.collect { |i| ["#{i.client.name} - #{number_to_currency(i.outstanding)}", i.id] }
  end
end

这样我可以在需要时重复使用下拉框并保持视图整洁。