105: def feature_module
106: unless defined?(@feature_module)
107: @features ||= {}
108: @feature_module = ::Module.new
109: const_set("FeatureModule", @feature_module)
110: features = @features
111:
112:
113: @feature_module.send(:define_method, :feature?) do |name|
114: method = name.to_s + "?"
115: return !!(respond_to?(method) and send(method))
116: end
117:
118:
119: @feature_module.send(:define_method, :features) do
120: return false unless defined?(features)
121: features.keys.find_all { |n| feature?(n) }.sort { |a,b|
122: a.to_s <=> b.to_s
123: }
124: end
125:
126:
127:
128: @feature_module.send(:define_method, :satisfies?) do |*needed|
129: ret = true
130: needed.flatten.each do |feature|
131: unless feature?(feature)
132: ret = false
133: break
134: end
135: end
136: ret
137: end
138:
139:
140:
141: @features.each do |name, feature|
142: method = name.to_s + "?"
143: @feature_module.send(:define_method, method) do
144: (is_a?(Class) ? declared_feature?(name) : self.class.declared_feature?(name)) or feature.available?(self)
145: end
146: end
147:
148:
149: @feature_module.send(:define_method, :has_features) do |*names|
150: @declared_features ||= []
151: names.each do |name|
152: name = symbolize(name)
153: @declared_features << name
154: end
155: end
156:
157: @feature_module.send(:alias_method, :has_feature, :has_features)
158: end
159: @feature_module
160: end