Ruby, DI внутри другого цикла класса

#ruby #loops #oop #dependency-injection

#ruby #циклы #ооп #внедрение зависимостей

Вопрос:

Я столкнулся с некоторыми препятствиями, когда попытался внедрить зависимость внутри этого кода, цель состоит в том, чтобы передать объект функции, вводящей зависимость. Я пробовал это с помощью procs, но это не имеет никакого смысла, поскольку proc parser = Proc.new { Parser.new } вызвал новый объект, но аргументы, переданные после инициализации, я не пробовал лямбды и чувствую, что полностью заблудился, найдя способ, который не нарушает стиль Ruby. Пожалуйста, помогите мне.

Вот код:

 class Interface
  attr_reader :data, :parser

  def initialize(data = [1, 2, 3], parser = Parser.new)
    @data = data
    @parser = parser
  end

  def parse_fresh_reports
    data.each do |datum|
      parser.new(datum).run
    end
  end
end

class Parser
  attr_accessor :datum
  
  def initialize(datum)
    @datum = datum 
  end 
 
  def parse_report
    puts "from #{self.inspect} #{datum}"
  end
end

Interface.new.parse_fresh_reports
  

Я хочу что-то вроде этого

 class Interface
  attr_accessor :data, :parser

  def initialize(data = [1, 2, 3], parser = Parser)
    @data = data
    @parser = parser
  end

  def parse_fresh_reports
    data.each do |datum|
      parser.run(datum)
    end
  end
end

class Parser
  attr_accessor :datum
  
  def self.run(datum)
    set_params(datum)
    parse_report
  end

  def set_params(datum)
    @datum = datum
  end

  def parse_report
    puts "from #{self.inspect} #{datum}"
  end
end

Interface.new.parse_fresh_reports


  

Я не знаю, можно ли передавать const в качестве аргумента.

Ответ №1:

parser = Parser.new не работает, потому Parser.new что требуется аргумент.

Вы можете передать константу, она передаст содержимое этой константы. В данном случае класс синтаксического анализатора. Это объект класса. Но то, как вы написали класс синтаксического анализатора, смешивает методы класса, например self.run , с методами экземпляра, такими как set_params . Чтобы заставить его работать, вам нужно было бы сделать все методом класса.

 class Parser
  # Everything inside the following block affects the class Parser.
  # Not instances of Parser.
  class << self
    attr_accessor :datum
    
    def run(datum)
      set_params(datum)
      parse_report
    end

    def set_params(datum)
      @datum = datum
    end

    def parse_report
      puts "from #{self.inspect} #{datum}"
    end
  end
end
  

Однако это означает, что одновременно может выполняться только один синтаксический анализ.


Вместо этого передайте новый объект синтаксического анализатора, а затем передайте ему его данные. Его можно передать прямо run .

 class Interface
  attr_reader :data, :parser

  def initialize(data = [1, 2, 3], parser = Parser.new)
    @data = data
    @parser = parser
  end

  def parse_fresh_reports
    data.each do |datum|
      # Pass the datum directly to each run.
      parser.run(datum)
    end
  end
end

class Parser
  def run(datum)
    puts "from #{inspect} #{datum}"
  end
end

Interface.new.parse_fresh_reports
  

Это позволяет передавать другие синтаксические анализаторы.

 class MyParser < Parser
  def run(*)
    super
    puts "Me, too!"
  end
end

Interface.new([1, 2, 3], MyParser.new).parse_fresh_reports