# frozen_string_literal: true module SiteHealth module EventEmitter # Returns an event emitter class with given event names # @return [Object] the event emitter class # @param [String, Symbol] event_names # @example Simple event emitter # class CrawlEvent < EventEmitter.define(:found_url, :page_title) # end # # event = CrawlEvent.new do |on| # on.every_found_url { {|url| puts "Found URL: #{url}" } # on.every_page_title { {|title| puts "Page title: #{title}" } # # you can add multiple blocks # on.every_page_title do |title| # puts "[WARNING] Title too long!: #{title}" if title.length > 155 # end # end # # event.emit_page_title(page_title) # event.emmit_found_url(url) def self.define(*event_names) # rubocop:disable Metrics/BlockLength Class.new do def initialize yield(self) if block_given? end define_method(:events) { event_names } event_names.each do |name| define_method(:emit) do |*args| public_send("emit_#{args.shift}", *args) end define_method("emit_#{name}") do |*args| blocks_for(name).each { |block| block.call(*args) } end define_method(:emit_each) do |*args| public_send("emit_each_#{args.shift}", *args) end define_method("emit_each_#{name}") do |array| blocks_for(name).each do |block| array.each { |o| block.call(o) } end end define_method("every_#{name}") do |*_args, &block| raise(ArgumentError, 'block must be given!') unless block blocks_for(name) << block end define_method(:blocks_for) do |block_name| variable_name = "@#{block_name}_blocks" if value = instance_variable_get(variable_name) value else instance_variable_set(variable_name, []) end end end end # rubocop:enable Metrics/BlockLength end end end