module ClassyEnum module Collection # Sort an array of elements based on the order they are defined # # ==== Example # # Create an Enum with some elements # class Priority < ClassyEnum::Base # end # # class Priority::Low < Priority; end # class Priority::Medium < Priority; end # class Priority::High < Priority; end # # @low = Priority.build(:low) # @medium = Priority.build(:medium) # @high = Priority.build(:high) # priorities = [@low, @high, @medium] # priorities.sort # => [@low, @medium, @high] # priorities.max # => @high # priorities.min # => @low def <=> other if other.is_a?(Symbol) || other.is_a?(String) other = self.class.find(other) end index <=> other.index end def enum_options self.class.enum_options end def self.included(klass) klass.extend ClassMethods end module ClassMethods include Enumerable alias all to_a def inherited(klass) if self == ClassyEnum::Base klass.class_eval do def self.enum_options @enum_options ||= superclass.enum_options end def self.enum_options=(options) @enum_options = options end end klass.enum_options = [] else enum_options << klass klass.instance_variable_set('@index', enum_options.size) end super end # Iterates over instances of each enum in the collection # # ==== Example # # Create an Enum with some elements # class Priority < ClassyEnum::Base # end # # class Priority::Low < Priority; end # class Priority::Medium < Priority; end # class Priority::High < Priority; end # # Priority.each do |priority| # puts priority # => 'Low', 'Medium', 'High' # end def each enum_options.each {|e| yield e.new } end # Returns the last enum instance in the collection # # ==== Example # # Create an Enum with some elements # class Priority < ClassyEnum::Base # end # # class Priority::Low < Priority; end # class Priority::Medium < Priority; end # class Priority::High < Priority; end # # Priority.last # => Priority::High def last to_a.last end # Finds an enum instance by symbol, string, or block. # # If a block is given, it passes each entry in enum to block, and returns # the first enum for which block is not false. If no enum matches, it # returns nil. # # ==== Example # # Create an Enum with some elements # class Priority < ClassyEnum::Base # end # # class Priority::Low < Priority; end # class Priority::Medium < Priority; end # class Priority::High < Priority; end # # Priority.find(:high) # => Priority::High.new # Priority.find('high') # => Priority::High.new # Priority.find {|e| e.to_sym == :high } # => Priority::High.new def find(key=nil) if block_given? super elsif map(&:to_s).include? key.to_s super { |e| e.to_s == key.to_s } end end alias detect find alias [] find # Returns a 2D array for Rails select helper options. # Also used internally for Formtastic support # # ==== Example # # Create an Enum with some elements # class Priority < ClassyEnum::Base # end # # class Priority::Low < Priority; end # class Priority::ReallyHigh < Priority; end # # Priority.select_options # => [["Low", "low"], ["Really High", "really_high"]] def select_options map {|e| [e.text, e.to_s] } end end end end