문제

나을 구현하기 위해 노력하고 method_missing 변환$다른 통화,으로 하기에 있는 5.달러 수익률 5,5.엔 수 0.065 5.유로 6.56 니다.이 수 있습니다.지금 나는야 그것을 구현하지만 일 5.달러이다.서(:yen)에 대한 예입니다.

이것은 내가 지금:

class Numeric
  @@currencies = {'yen' => 0.013, 'euro' => 1.292, 'rupee' => 0.019}
  def method_missing(method_id)
    singular_currency = method_id.to_s.gsub( /s$/, '')
    if @@currencies.has_key?(singular_currency)
      self * @@currencies[singular_currency]
    else
      super
    end
  end
end

할 수 있는 사람이 어떻게 설명할 수 있습니까?

PS:오히려 당신을 코드,하지만,설명할 수 있도록 확인에 나 자신의 방법에 그것이 수행됩니다.

도움이 되었습니까?

해결책

Perhaps this will be of more help. It's a working example (note, I'm expecting you to have ActiveSupport [part of Rails] and Ruby 1.9.2+):

require 'rubygems'

# This is allowing us to do the `pluralize` calls below
require 'active_support/inflector'

module Currency
  CONVERSION_TABLE = { dollars: { dollars: 1, euros: 0.75 }, euros: { dollars: 1.3333334, euros: 1 } }.freeze
  attr_accessor :currency

  def method_missing(method_name, *args, &block)
    # standardize on pluralized currency names internally so both singular
    # and plural methods are handled
    method_name = method_name.to_s.pluralize.to_sym

    # Use the "from" keys in the conversion table to verify this is a valid 
    # source currency
    if CONVERSION_TABLE.key?(method_name)
      @currency = method_name
      self # return self so a call to `1.dollar` returns `1` and not `:dollars`
    else
      super
    end
  end

  # Convert `self` from type of `@currency` to type of `destination_currency`, mark the result with
  # the appropriate currency type, and return. Example:
  def to(destination_currency)
    # Again, standardize on plural currency names internally
    destination_currency = destination_currency.to_s.pluralize.to_sym

    # Do some sanity checking
    raise UnspecifiedSourceCurrency unless defined?(@currency)
    raise UnsupportedDestinationCurrency unless CONVERSION_TABLE.key?(destination_currency)

    # Do the actual conversion, and round for sanity, though a better
    # option would be to use BigDecimal which is more suited to handling money
    result = (self * CONVERSION_TABLE[@currency][destination_currency]).round(2)

    # note that this is setting @currency through the accessor that
    # was created by calling `attr_accessor :currency` above
    result.currency = destination_currency
    result
  end
end

class Numeric
  # Take all the functionality from Currency and mix it into Numeric
  # 
  # Normally this would help us encapsulate, but right now it's just making
  # for cleaner reading. My original example contained more encapsulation
  # that avoided littering the Numeric clas, but it's harder for a beginner
  # to understand. For now, just start here and you will learn more later.
  include Currency
end

p 5.euros.to(:dollars)                #=> 6.67
p 0.25.dollars.to(:euro)              #=> 0.19
p 1.dollar.to(:euros).to(:dollar)     #=> 1.0

다른 팁

통화가 추가 된 통화 '달러'및 in 방법 :

class Numeric
  @@currencies = {'dollar' => 1, 'yen' => 0.013, 'euro' => 1.292, 'rupee' => 0.019}
  def method_missing(method_id)
    singular_currency = method_id.to_s.gsub(/s$/, '')
    if @@currencies.has_key?(singular_currency)
      self * @@currencies[singular_currency]
    else
      super
    end
  end

  def in(currency)
    singular_currency = currency.to_s.gsub(/s$/, '')
    self / @@currencies[singular_currency]
  end
end
.

이것은 더 많은 수학적 문제보다는 계산 하나입니다.

각각의 @@currencies 해쉬값은 정규화하는'달러':그들의 유닛 엔/달러, 유로/달러, 루피/달러.대 5.euro.in(:yen), 만 나눌 유로/달러 by 엔/달러 을 표현하는 답으로 유로 엔입니다.

계산에 이를 사용하여 루비,당신은 남 method_missing 방법을 변경하고 업데이트 클래스 일정을 포함 'dollar' => 1.추가 Numeric#in 하나인 메서드를 온라인 계산이 문제를 해결합니다.는 계산이 필요에 적용하는 부문에서 올바른 순서 부동 소수점 번호입니다.

5.euro.in(:yen) 예제는 기억, 5.euro 계산 먼저 하지만 단위 유로/달러.이 서(:yen) 메소드는 다음에 적용되어야의 상호 이 수 있습니다.이 숫자와 단위 엔 euro, 상호의 원하는 결과입니다.

지 않을 것을 그냥을 정의하는 방법이라고 in 보내는 상징이 다시 매개변수 self?

irb(main):057:0> 5.dollar.in(:euro)
=> 6.46
irb(main):065:0> 5.euro.in(:dollar)
=> 6.46 # Which is wrong, by the way

그래서,아주지 않기 때문에,알고 현재의 양을 나타냅--h method_missing 가정 모두에서 달러의 경우에도,그것은 아닙니다.

그 이유가 돈석 :)

method_missing를 사용하는 대신 각 통화를 반복하는 것이 더 쉽고 전환 방법에 위임하는 단수 및 복수의 방법을 정의 할 수 있습니다.

편의를 위해 ActiveSupport가 있으면 여기를 가정합니다.당신은 이것을하지 않고이 일을 할 수 있지만, constantize와 우려는 더 쉽게 만들 수 있습니다.

module DavesMoney
  class BaseMoney
    # your implementation
  end

  class DollarConverter < BaseMoney
    def initialize(value)
      @value = value
    end

    def to(:currency)
      # implemented in `BaseMoney` that gets extended (or included)
    end
  end
end

module CurrencyExtension
  extend ActiveSupport::Concern

  SUPPORTED_CURRENCIES = %w{ dollar yen euro rupee }

  included do
    SUPPORTED_CURRENCIES.each do |currency|
      define_method :"#{currency}" do
        return "#{currency}_converter".constantize.new(self)
      end
      alias :"#{currency.pluralize}" :"#{currency}"
    end
  end
end

# extension
class Numeric
  include CurrencyExtension
end
.

내 방식을 이에 따라,수락의 한계에 문제가 제기(확장 method_missing 구현에 숫자도로@coreyward 음을 나타냅 이것은 정말 잘못된 접근 방식이 아무것도 숙제)다음과 같습니다:

이해 5.euros.in(:yen) 번역될 수 있습니다:

eur = 5.send(:euros)
eur.send( :in, yen )

what's 근본적으로 일어나는 우리가 보내는 유로 메시지가 숫자 5 한 후 발송 in 하는 방법 숫자의 결과 5.유로의 매개변수:엔입니다.

에 method_missing 에 대응해야 합 euros 호출하고 그 결과의 유로 달러를 변환한 다음,(또한 method_missing)에 대응 in 화의 결과로 변환 달러(에서 이전 호출)을 상징으로 전달된 매개 변수 in 전화입니다.을 반환하는 적절한 값입니다.

물론으로 변환할 수 있습에서 어떤 통화는 그래서 당신이 원하는 장으로의 변환 요소는 올바른-와 흥이 특정 문제에 대한 변환에서 달러 듯한 가장 합리적이다.

나는이 과정을하고있다. 그리고 나는 그 일을 성취하는 방법에 대한 몇 가지 예를 보았다.어떤 시점에서는 self.send가 언급되었고 다른 누군가가 또한 이것을 구현했다고 믿었지만이 솔루션을 찾았습니다.

https://gist.github.com/2065412

여기에 내가 한 일이 있습니다 ...

http://pastebin.com/dpe8vah4

    class Numeric
      @@currencies = {'yen' => 0.013, 'euro' => 1.292, 'rupee' => 0.019, 'dollar' => 1}
      def method_missing(method, *arg)
        singular_currency = method.to_s.gsub(/s$/,'')
        if @@currencies.has_key?(singular_currency)
          self * @@currencies[singular_currency]
        else
          super
        end
      end
      def in(arg)
        singular_currency = arg.to_s.gsub(/s$/,'')
        if @@currencies.has_key?(singular_currency)
          self * @@currencies[singular_currency]
        end
      end
    end

    puts "5.euro = "+5.euro.to_s
    puts "5.euros = "+5.euros.to_s
    puts "5.dollars.in(:euros) = "+5.dollars.in(:euros).to_s
    puts "10.euros.in(:rupees) = "+10.euros.in(:rupees).to_s
.

  • add "add"
  • 메소드 _MISSING 메서드에 새로운 인수를 추가 ", * args"
  • 새로운 메소드를 숫자 클래스에 "in (arg)"에 추가하십시오.
  • 이 메서드는 인수 "arg"에 지정된 통화로 자체를 곱합니다.

먼저 단위 라이브러리를 설치하십시오. gem install sy.그런 다음 정의 :

require 'sy'
Money = SY::Quantity.dimensionless      #=> #<Quantity:Money>
USD = SY::Unit.standard of: Money       #=> #<Unit:USD of Money >
YEN = SY::Unit.of Money, amount: 0.013  #=> #<Unit:YEN of Money >
EUR = SY::Unit.of Money, amount: 1.292  #=> #<Unit:EUR of Money >
INR = SY::Unit.of Money, amount: 0.019  #=> #<Unit:INR of Money >
.

이제는 계산할 수 있습니다 :

10 * 10.usd => #<Magnitude: 100 >
100.yen.in :usd #=> #<Magnitude: 1.3 >
1.eur + 1.usd #=> #<Magnitude: 2.29 >
.

를 정의 할 수도 있습니다.

CENT = SY::Unit.of Money, amount: 0.01.usd
EUROCENT = SY::Unit.of Money, amount: 0.01.eur
.

및 그 다음

12.usd + 90.cent #=> #<Magnitude: 12.9 >
.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top