您想要的功能自然适合 Array 继承的 Enumerable 的选择。
因为您正在谈论一个列表,AKA,数组,所以很自然地适合使用 select 来确定您的电影是否符合您的标准,而不是将它们传递给方法。
单独的 Filter 类也不适合 Ruby 方式。考虑为您的电影列表子类化 Array,并添加一个将您的条件作为参数的过滤器方法。
以下是我编写该功能的方式,但以我认为更像 Ruby 的方式进行:
require 'pp'
class Movies < Array
def initialize(*movies)
super(movies)
end
def filter(criteria={})
self.select{ |m|
criteria.all?{ |c, v|
m.send(c, v)
}
}
end
end
class Movie
def initialize(attributes={})
@movie = attributes
end
def name(t)
case t
when Regexp
@movie[:name][t]
when String
@movie[:name] == t
end
end
def genre(g)
@movie[:genre] == g
end
def year(y)
@movie[:year] == y
end
end
movies = Movies.new(
Movie.new(name: 'Batman', genre: 'Drama', year: 2001),
Movie.new(name: 'The Shawshank Redemption', genre: 'Drama', year: 1994),
Movie.new(name: 'Raiders of the Lost Ark', genre: 'Action', year: 1981)
)
pp movies.filter(year: 1981)
pp movies.filter(genre: 'Drama', year: 2001)
pp movies.filter(name: /redemption/i)
我对 Movie 类使用了哈希,因为它更快。这也是一种更肮脏的方式,但它确实有效。
这是运行代码的输出:
[#<Movie:0x007ff7b191ffb8
@movie={:name=>"Raiders of the Lost Ark", :genre=>"Action", :year=>1981}>]
[#<Movie:0x007ff7b1920260
@movie={:name=>"Batman", :genre=>"Drama", :year=>2001}>]
[#<Movie:0x007ff7b19200d0
@movie={:name=>"The Shawshank Redemption", :genre=>"Drama", :year=>1994}>]
过滤电影的实际流程适合我们通常编写 Ruby 代码的方式。它可以做得更好,但这是一个开始。