开发者

Is it possible to simulate the behaviour of sprintf("%g") using the Rails NumberHelper methods?

sprintf("%g", [float]) allows me to format a floating point number without specifying precision, such that 10.00 is rendered as 10 and 10.01 is rendered as 10.01, and so on. This is neat.

In my application I'm rendering numbers using the 开发者_Python百科Rails NumberHelper methods so that I can take advantage of the localization features, but I can't figure out how to achieve the above functionality through these helpers since they expect an explicit :precision option.

Is there a simple way around this?


Why not just use Ruby's Kernel::sprintf with NumberHelper? Recommended usage with this syntax: str % arg where str is the format string (%g in your case):


>> "%g" % 10.01
=> "10.01"
>> "%g" % 10
=> "10"

Then you can use the NumberHelper to print just the currency symbol:


>>  foo = ActionView::Base.new
>>  foo.number_to_currency(0, :format => "%u") + "%g"%10.0 
=> "$10"

and define your own convenience method:


 def pretty_currency(val) 
    number_to_currency(0, :format => "%u") + "%g"%val
 end

pretty_currency(10.0)  # "$10"
pretty_currency(10.01) # "$10.01"


I have solved this by adding another method to the NumberHelper module as follows:

module ActionView
  module Helpers #:nodoc:
    module NumberHelper
      # Formats a +number+ such that the the level of precision is determined using the logic of sprintf("%g%"), that
      # is: "Convert a floating point number using exponential form if the exponent is less than -4 or greater than or
      #      equal to the precision, or in d.dddd form otherwise."
      # You can customize the format in the +options+ hash.
      #
      # ==== Options
      # * <tt>:separator</tt>  - Sets the separator between the units (defaults to ".").
      # * <tt>:delimiter</tt>  - Sets the thousands delimiter (defaults to "").
      #
      # ==== Examples
      #  number_with_auto_precision(111.2345)                    # => "111.2345"
      #  number_with_auto_precision(111)                         # => "111"
      #  number_with_auto_precision(1111.2345, :separator => ',', :delimiter => '.')  # "1,111.2345"
      #  number_with_auto_precision(1111, :separator => ',', :delimiter => '.')       # "1,111"
      def number_with_auto_precision(number, *args)
        options = args.extract_options!
        options.symbolize_keys!

        defaults           = I18n.translate(:'number.format', :locale => options[:locale], :raise => true) rescue {}
        separator ||= (options[:separator] || defaults[:separator])
        delimiter ||= (options[:delimiter] || defaults[:delimiter])

        begin
          number_with_delimiter("%g" % number,
            :separator => separator,
            :delimiter => delimiter)
        rescue
          number
        end
      end
    end
  end
end

It is the specific call to number_with_delimiter with the %g option which renders the number as described in the code comments above.

This works great for me, but I'd welcome thoughts on this solution.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜