Как я могу создать экземпляры класса ruby ​​​​из хэш-массива?

У меня есть модуль FDParser, который читает файл csv и возвращает хороший массив хэшей, каждый из которых выглядит следующим образом:

{
  :name_of_investment => "Zenith Birla",
  :type => "half-yearly interest",
  :folio_no => "52357",
  :principal_amount => "150000",
  :date_of_commencement => "14/05/2010",
  :period => "3 years",
  :rate_of_interest => "11.25"
}

Теперь у меня есть класс Investment, который принимает приведенный выше хэш в качестве входных данных и преобразует каждый атрибут в соответствии с тем, что мне нужно.

class Investment
  attr_reader :name_of_investment, :type, :folio_no,
              :principal_amount, :date_of_commencement,
              :period, :rate_of_interest

  def initialize(hash_data)
    @name = hash_data[:name_of_investment]
    @type = hash_data[:type]
    @folio_no = hash_data[:folio_no]
    @initial_deposit = hash_data[:principal_amount]
    @started_on =hash_data[:date_of_commencement]
    @term = hash_data[:period]
    @rate_of_interest = hash_data[:rate_of_interest]
  end

  def type
    #-- custom transformation here
  end
end

У меня также есть класс Porfolio, с помощью которого я хочу управлять коллекцией объектов investment. Вот как выглядит класс Portfolio:

class Portfolio
  include Enumerable
  attr_reader :investments

  def initialize(investments)
    @investments = investments
  end

  def each &block
    @investments.each do |investment|
      if block_given?
        block.call investment
      else
        yield investment
      end
    end
  end
end

Теперь я хочу перебрать investment_data, полученный модулем, и динамически создать экземпляры инвестиционного класса, а затем отправить эти экземпляры в качестве входных данных в класс Portfolio.

До сих пор я пробовал:

FDParser.investment_data.each_with_index do |data, index|
  "inv#{index+1}" = Investment.new(data)
end

Но, очевидно, это не работает, потому что вместо экземпляра объекта я получаю строку. Как правильно отправить коллекцию экземпляров в перечисляемый класс коллекции, который затем сможет ими управлять?


person Amit Erandole    schedule 17.10.2014    source источник


Ответы (1)


Я не уверен, что означает "отправить в качестве входных данных в класс Portfolio"; сами классы не принимают "ввод". Но если вы просто пытаетесь добавить объекты Investment в переменную экземпляра @investments внутри экземпляра Portfolio, попробуйте следующее:

portfolio = Portfolio.new([])

FDParser.investment_data.each do |data|
  portfolio.investments << Investment.new(data)
end

Обратите внимание, что литерал массива [] и возвращаемое значение portfolio.investments указывают здесь на один и тот же объект Array. Это означает, что вы могли бы эквивалентно сделать это, что, возможно, немного яснее:

investments = []

FDParser.investment_data.each do |data|
  investments << Investment.new(data)
end

Portfolio.new(investments)

И если вы хотите немного поиграть в код-гольф, он еще больше уменьшится, если вы используете map.

investments = FDParser.investment_data.map {|data| Investment.new(data) }

Portfolio.new(investments)

Я думаю, что это немного сложнее читать, чем предыдущий вариант.

person user513951    schedule 17.10.2014