Петко обнови решението на 27.10.2012 17:32 (преди над 12 години)
+require 'enumerator'
+require 'forwardable'
+
+class Collection
+ include Enumerable
+ extend Forwardable
+
+ def self.parse(text)
+ new text.split("\n\n").map { |block| Song.new block }
+ end
+
+ def initialize(songs)
+ @songs = songs
+ end
+
+ def_delegator :@songs, :each
+end
+
+class Song
+ attr_accessor :name, :artist, :album
+
+ def initialize(block)
+ @name, @artist, @album = block.split "\n"
+ end
+end
+
+class Criteria
+ def initialize(tags, inclusive = true)
+ @tags, @inclusive = tags, inclusive
+ end
+
+ def self.name(name)
+ new name: name
+ end
+
+ def self.artist(artist)
+ new artist: artist
+ end
+
+ def self.album(album)
+ new album: album
+ end
+
+ def inclusive?
+ @inclusive
+ end
+
+ def !()
+ Criteria.new @tags, !@inclusive
+ end
+end
Единственото, което намирам за много крива идея, е да подаваш текстов блок на конструктора на Song
. По-добре подай три позиционни аргумента и остави парсенето на някой друг.
Иначе - пушка.