13
13
# To make a feature conditionally supported, pass a block to the +supports+ method.
14
14
# The block is evaluated in the context of the instance.
15
15
# If a feature is not supported, return a string for the reason. A nil means it is supported
16
- # Alternatively, calling the private method +unsupported_reason_add+ with the feature
17
- # and a reason, marks the feature as unsupported, and the reason will be
18
- # accessible through
16
+ # The reason will be accessible through
19
17
#
20
18
# instance.unsupported_reason(:feature)
21
19
#
@@ -50,9 +48,7 @@ module SupportsFeatureMixin
50
48
# Whenever this mixin is included we define all features as unsupported by default.
51
49
# This way we can query for every feature
52
50
included do
53
- private_class_method :unsupported
54
- private_class_method :unsupported_reason_add
55
- class_attribute :supports_features , :instance_writer => false , :default => { }
51
+ class_attribute :supports_features , :instance_writer => false , :instance_reader => false , :default => { }
56
52
end
57
53
58
54
def self . default_supports_reason
@@ -61,29 +57,16 @@ def self.default_supports_reason
61
57
62
58
# query instance for the reason why the feature is unsupported
63
59
def unsupported_reason ( feature )
64
- feature = feature . to_sym
65
- supports? ( feature ) unless unsupported . key? ( feature )
66
- unsupported [ feature ]
60
+ self . class . unsupported_reason ( feature , :instance => self )
67
61
end
68
62
69
63
# query the instance if the feature is supported or not
70
64
def supports? ( feature )
71
- self . class . check_supports ( feature . to_sym , :instance => self )
65
+ ! unsupported_reason ( feature )
72
66
end
73
67
74
68
private
75
69
76
- # used inside a +supports+ block to add a reason why the feature is not supported
77
- # just adding a reason will make the feature unsupported
78
- def unsupported_reason_add ( feature , reason )
79
- feature = feature . to_sym
80
- unsupported [ feature ] = reason
81
- end
82
-
83
- def unsupported
84
- @unsupported ||= { }
85
- end
86
-
87
70
class_methods do
88
71
# This is the DSL used a class level to define what is supported
89
72
def supports ( feature , &block )
@@ -96,34 +79,26 @@ def supports_not(feature, reason: nil)
96
79
self . supports_features = supports_features . merge ( feature . to_sym => reason . presence || false )
97
80
end
98
81
99
- # query the class if the feature is supported or not
100
82
def supports? ( feature )
101
- check_supports ( feature . to_sym , :instance => self )
83
+ ! unsupported_reason ( feature )
102
84
end
103
85
104
- def check_supports ( feature , instance :)
105
- instance . send ( :unsupported ) . delete ( feature )
106
-
86
+ # query the class if the feature is supported or not
87
+ def unsupported_reason ( feature , instance : self )
107
88
# undeclared features are not supported
108
89
value = supports_features [ feature . to_sym ]
109
-
110
90
if value . respond_to? ( :call )
111
91
begin
112
92
# for class level supports, blocks are not evaluated and assumed to be true
113
93
result = instance . instance_eval ( &value ) unless instance . kind_of? ( Class )
114
- # if no errors yet but result was an error message
115
- # then add the error
116
- if !instance . send ( :unsupported ) . key? ( feature ) && result . kind_of? ( String )
117
- instance . send ( :unsupported_reason_add , feature , result )
118
- end
94
+ result if result . kind_of? ( String )
119
95
rescue => e
120
96
_log . log_backtrace ( e )
121
- instance . send ( :unsupported_reason_add , feature , "Internal Error: #{ e . message } " )
97
+ "Internal Error: #{ e . message } "
122
98
end
123
99
elsif value != true
124
- instance . send ( :unsupported_reason_add , feature , value || SupportsFeatureMixin . default_supports_reason )
100
+ value || SupportsFeatureMixin . default_supports_reason
125
101
end
126
- !instance . send ( :unsupported ) . key? ( feature )
127
102
end
128
103
129
104
# all subclasses that are considered for supporting features
@@ -158,23 +133,5 @@ def supporting(feature)
158
133
def providers_supporting ( feature )
159
134
ExtManagementSystem . where ( :type => provider_classes_supporting ( feature ) . map ( &:name ) )
160
135
end
161
-
162
- # query the class for the reason why something is unsupported
163
- def unsupported_reason ( feature )
164
- feature = feature . to_sym
165
- supports? ( feature ) unless unsupported . key? ( feature )
166
- unsupported [ feature ]
167
- end
168
-
169
- def unsupported
170
- # This is a class variable and it might be modified during runtime
171
- # because we do not eager load all classes at boot time, so it needs to be thread safe
172
- @unsupported ||= Concurrent ::Hash . new
173
- end
174
-
175
- # use this for making a class not support a feature
176
- def unsupported_reason_add ( feature , reason )
177
- unsupported [ feature . to_sym ] = reason
178
- end
179
136
end
180
137
end
0 commit comments