@@ -15,6 +15,14 @@ module Attachable
1515 # The explicit values that flip +present+ to its unattached side.
1616 FALSE_VALUES = [ false , 0 , '0' , 'false' ] . freeze
1717
18+ # The symbolic +type+ shortcuts, each expanded lazily at query time against
19+ # ActiveStorage's configured content-type lists — never frozen at boot, and
20+ # only ever called once the model proved it has real attachments, so the
21+ # gem still loads without ActiveStorage.
22+ TYPE_SHORTCUTS = {
23+ 'image' => -> { ActiveStorage . variable_content_types | ActiveStorage . web_image_content_types }
24+ } . freeze
25+
1826 module_function
1927
2028 # Narrows the scope from each accepted attachment key.
@@ -72,12 +80,37 @@ def accepted(params, scope)
7280 def entries ( name , attachment , bounds )
7381 [
7482 [ :present , presence_value ( bounds ) ] ,
75- [ :type , Filterable :: ValueNormalization . normalize ( bounds [ :type ] ) ] ,
83+ [ :type , content_types ( bounds [ :type ] ) ] ,
7684 [ :min_size , Filterable ::Rangeable . parse ( bounds [ :min_size ] ) ] ,
7785 [ :max_size , Filterable ::Rangeable . parse ( bounds [ :max_size ] ) ]
7886 ] . filter_map { |key , value | [ name , attachment , key , value , bounds [ key ] ] unless value . nil? }
7987 end
8088
89+ # The normalized +type+ value, with symbolic shortcuts expanded. A real
90+ # content type always carries a slash, so a known shortcut name is
91+ # unambiguous; an unknown literal stays a plain equality that matches
92+ # nothing, never a silent no-op.
93+ #
94+ # @api private
95+ # @param raw [Object] the raw +type+ value.
96+ # @return [String, Array, nil] the usable content type(s), or nil.
97+ def content_types ( raw )
98+ Filterable ::ValueNormalization . normalize ( expand_types ( raw ) )
99+ end
100+
101+ # Expands every known shortcut in a raw +type+ value, leaving everything
102+ # else untouched.
103+ #
104+ # @api private
105+ # @param raw [Object] the raw +type+ value, scalar or array.
106+ # @return [Object] the value with shortcuts replaced by content-type lists.
107+ def expand_types ( raw )
108+ return raw . flat_map { |value | expand_types ( value ) } if raw . is_a? ( Array )
109+
110+ shortcut = TYPE_SHORTCUTS [ raw . to_s ]
111+ shortcut ? shortcut . call : raw
112+ end
113+
81114 # How a +present+ key reads: +:attached+ on a strict true or bare key,
82115 # +:missing+ on an explicit false, nil otherwise.
83116 #
0 commit comments