I am trying to implement a filter-by-criteria approach in a little project of mine. I have a Filter class, in which i have filters for name, year, genre. For example:
Filter.new.name("The Shawshank Redemption")
Filter.new.year("1994")
Filter.new.genre("drama")
I also have a list of movies, each being an object that has methods name, year and genre. I want to be able to do the following (MoviesContainer is just a class that has a @movies list):
MoviesContainer.filter Filter.new.name("The Godfather") & Filter.new.year("1972") | Filter.year("1974")
I can easily overload the |, & and ! operators in my Filter class, but I don't know how to combine the filter object so that they become just one object which I can pass to filter. I'm gladly accepting any ideas. :)
My best idea so far is to create a proc for every Filter.new and then combine them in the &,| and ! methods, but I don't know how. I'm thinking something like this could work, however, it doesn't :D
proc { |movie| proc { |movie| movie.name == "The Godfather" } && proc { |movie| movie.year== "1972" }
and then call this with every of the @movies items. Can you please help me with the combining procs thing, or perhaps propose a better solution. Thank you.
Maybe something like this?
class Filter
attr_accessor :proc
class <<self; alias :old_new :new end
def self.new attribute, value
old_new.tap{|f| f.proc = ->x{x.send(attribute) == value}}
end
def & other
self.class.old_new.tap{|f| f.proc = ->x{proc.call(x) && other.proc.call(x)}}
end
def | other
self.class.old_new.tap{|f| f.proc = ->x{proc.call(x) || other.proc.call(x)}}
end
def !
self.class.old_new.tap{|f| f.proc = ->x{!proc.call(x)}}
end
end
class Movie
attr_accessor :name, :year, :genre
end
MoviesContainer = [
Movie.new.tap{|m| m.name = "The Godfather"; m.year = "1972"},
Movie.new
]
module Enumerable
def filter f
select(&f.proc)
end
end
filter1 = Filter.new(:name, "The Godfather")
filter2 = Filter.new(:year, "1972")
filter3 = Filter.new(:year, "1974")
MoviesContainer.filter(filter1 & filter2 | filter3)
# => [#<Movie:0x000000017dba08 @name="The Godfather", @year="1972">]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.