Skip to content

Instantly share code, notes, and snippets.

@adrienpoly
Forked from fractaledmind/has_many_attached.rb
Created October 26, 2023 06:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adrienpoly/068e99af8b26e2d18ae0f12ef1bcd6bf to your computer and use it in GitHub Desktop.
Save adrienpoly/068e99af8b26e2d18ae0f12ef1bcd6bf to your computer and use it in GitHub Desktop.
Vanilla Rails isomorphic attachment validations
# /app/models/concerns/has_many_attached.rb
module HasManyAttached
extend ActiveSupport::Concern
class_methods do
def has_many_attached(name, dependent: :purge_later, service: nil, strict_loading: false, **options)
super(name, dependent: :purge_later, service: nil, strict_loading: false)
if options[:file_types].any?
validate "validate_#{name}_file_types".to_sym
singleton_class.define_method("#{name}_file_types") do
options[:file_types]
end
define_method("validate_#{name}_file_types") do
items = public_send(name)
return unless items.attached?
validations = options[:file_types].map { |type| Regexp.new(type.sub('*', '.*')) }
items.each do |item|
next if validations.any? { |validation| item.content_type.match?(validation) }
errors.add(name.to_sym, :invalid_type, type: item.content_type)
end
end
end
end
end
end
# /app/models/my_model.rb
class MyModel < ApplicationRecord
include HasManyAttached
has_many_attached :files,
dependent: :destroy,
file_types: ["image/*", "video/*"]
end
<%= form_with(model: my_model) do |form| %>
<%= form.file_field :files,
multiple: true,
accept: form.object.class.files_file_types.join(', ') %>
<% end %>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment