Ruby on rails 导轨中的干燥视图(编号到货币)

Ruby on rails 导轨中的干燥视图(编号到货币),ruby-on-rails,views,dry,Ruby On Rails,Views,Dry,我的代码类似于: number\u to\u currency(行\u item.price,:unit=>“£”) 在各种模型中乱扔我的观点。由于我的应用程序只处理英镑(£),我是否应该将其移动到我的每个模型中,以便line\u item.price按原样返回字符串(即number\u to\u currency(line\u item.price,:unit=>“£”)和line\u item.price都是相同的。我认为要这样做,我应该: def price number_to_curr

我的代码类似于:

number\u to\u currency(行\u item.price,:unit=>“£”)

在各种模型中乱扔我的观点。由于我的应用程序只处理英镑(£),我是否应该将其移动到我的每个模型中,以便
line\u item.price
按原样返回字符串(即
number\u to\u currency(line\u item.price,:unit=>“£”)
line\u item.price
都是相同的。我认为要这样做,我应该:

def price
 number_to_currency(self.price, :unit => "£")
end

但是这不起作用。如果模型中已经定义了
price
,那么Rails会报告“堆栈级别太深”,当我将
def price
更改为
def amount
时,它会抱怨没有定义
number\u to\u currency

number\u to\u currency是一个视图帮助程序,因此在模型中不可用

您可以通过在application_helper.rb中定义自己的助手来保存一些关键笔划(因此它对所有视图都可用)

然后在视图中调用它:

quid(line_item.price)
堆栈级别错误太深的原因是,当您在
price
方法中说
self.price
时,您正在创建一个对price方法的无限递归调用,因为您现在已经覆盖了普通的访问器方法。要避免这种情况,您需要使用属性哈希访问price字段的值。例如,so方法如下:

def price
 number_to_currency(attributes['price'], :unit => "£")
end
# /RAILS_ROOT/lib/your_namespace/helper.rb
#
# Need to access helpers in the model?
# YourNamespace::Helper.instance.helper_method_name
module YourNamespace
  class Helper
    include Singleton
    include ActionView::Helpers
  end
end

除了由于Larry K所描述的原因,
number\u to\u currency
在模型代码中不可用之外。

关于制作另一个助手方法quid(price)的另一个答案简化重复可能是最好的方法。但是,如果您确实想访问模型中的视图帮助程序,可以执行以下操作:

def price
 number_to_currency(attributes['price'], :unit => "£")
end
# /RAILS_ROOT/lib/your_namespace/helper.rb
#
# Need to access helpers in the model?
# YourNamespace::Helper.instance.helper_method_name
module YourNamespace
  class Helper
    include Singleton
    include ActionView::Helpers
  end
end
然后,您应该能够在模型类中执行此操作:

def price
  helper = YourNamespace::Helper.instance
  helper.number_to_currency(read_attribute('price'), :unit => "£")
end

这是我解决这个问题的方法

# /RAILS_ROOT/lib/app_name/currency_helper.rb
module AppName
  module CurrencyHelper    

    include ActionView::Helpers::NumberHelper

    def number_to_currency_with_pound(amount, options = {})
      options.reverse_merge!({ :unit => '£' })
      number_to_currency_without_pound(amount, options)
    end

    alias_method_chain :number_to_currency, :pound

  end
end
在您的模型中,您可以做到这一点(并且您不会用不打算使用的方法污染您的模型)

现在,无论您在何处使用“数字到货币”帮助器,它都将使用英镑符号进行格式化,但您也具有原始rails方法的所有灵活性,因此您可以像以前一样传递选项

number_to_currency(amount, :unit => '$')

将其转换回美元符号。

如果要更改整个应用程序的默认值,可以编辑config/locales/en.yml

我的看起来像这样:

# Sample localization file for English. Add more files in this directory for other locales.
# See http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
"en":
  number:
    currency:
        format:
            format: "%u%n"
            unit: "£"
            # These three are to override number.format and are optional
            separator: "."
            delimiter: ","
            precision: 2

除了单位之外的所有内容都是可选的,并将返回默认值,但我将其输入,以便知道可以更改哪些值。从Rails 3开始,您也可以使用英镑符号而不是£;

正如Larry K所描述的,但通过此编辑:

def quid(price)
   number_to_currency(price, :unit => "£")
 end

感谢您向我解释递归调用位。如果您可以将默认单位设置为GBP,并直接使用数字到货币,这不是更枯燥吗?感谢您的提示;
ActionView::Helpers::NumberHelper number\u到货币()
的Rails API文档给出了一个设置
:locale=>“fr”的示例
更改分隔符和分隔符以及货币符号的位置。这对我来说不起作用,但通过添加一个
config/locales/fr.yml
和上面的设置,它开始起作用。我一直使用一个自定义帮助器,类似于Larry K的公认答案所描述的,但这要干净得多。
def quid(price)
   number_to_currency(price, :unit => "£")
 end