Skip to content

Commit

Permalink
Simplify #file_method? implementation
Browse files Browse the repository at this point in the history
It turns out that some methods are available in more than one Gem, so I
tried to group things to make it simpler and easier to maintain.
I also removed the support for multiple file uploads, because those are
very application-specific, it didn't seem worth the cost of the
complexity/maintainence.
  • Loading branch information
tegon committed Sep 27, 2019
1 parent 3a4c01d commit a25950f
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 81 deletions.
46 changes: 20 additions & 26 deletions lib/simple_form/form_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -572,34 +572,28 @@ def find_custom_type(attribute_name)
}.try(:last) if SimpleForm.input_mappings
end

# Internal: Try to discover whether an attribute corresponds to a file.
#
# Most upload Gems add some kind of attributes to the ActiveRecord's model they are included in.
# This method tries to guess if an attribute belongs to some of these Gems by checking the presence
# of their methods using `#respond_to?`.
#
# Note: this does not support multiple file upload inputs, as this is very application-specific.
#
# The order here was choosen based on the popularity of the Gems and for commodity - e.g. the method
# with the suffix `_url` is present in three Gems, so it's checked with priority:
#
# - `#{attribute_name}_attachment` - ActiveStorage >= `5.2` and Refile >= `0.2.0` <= `0.4.0`
# - `#{attribute_name}_url` - Shrine >= `0.9.0`, Refile >= `0.6.0` and CarrierWave >= `0.2.1`
# - `#{attribute_name}_attacher` - Refile >= `0.4.0` and Shrine >= `0.9.0`
# - `#{attribute_name}_file_name` - Paperclip ~> `2.0` (added for backwards compatibility)
#
# Returns a Boolean.
def file_method?(attribute_name)
activestorage?(attribute_name) || shrine?(attribute_name) ||
carrierwave?(attribute_name) || paperclip?(attribute_name) ||
refile?(attribute_name)
end

def activestorage?(attribute_name)
@object.class.try(:reflect_on_attachment, attribute_name).present? ||
@object.class.try(:reflect_on_association, "#{attribute_name}_attachment").present? ||
@object.class.try(:reflect_on_association, "#{attribute_name}_attachments").present?
end

def shrine?(attribute_name)
@object.respond_to?("#{attribute_name}_attacher")
end

def carrierwave?(attribute_name)
@object.respond_to?("#{attribute_name}_url") ||
@object.respond_to?("#{attribute_name}_urls")
end

def paperclip?(attribute_name)
@object.respond_to?("#{attribute_name}_file_name")
end

def refile?(attribute_name)
@object.respond_to?("#{attribute_name}_attachment") ||
@object.respond_to?("#{attribute_name}_attachment_definition")
@object.respond_to?("#{attribute_name}_url") ||
@object.respond_to?("#{attribute_name}_attacher") ||
@object.respond_to?("#{attribute_name}_file_name")
end

def find_attribute_column(attribute_name)
Expand Down
41 changes: 8 additions & 33 deletions test/form_builder/general_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -239,49 +239,24 @@ def with_custom_form_for(object, *args, &block)
assert_select 'form select#user_updated_at_1i.datetime'
end

test 'builder generates file input for activestorage' do
test 'builder generates file input for ActiveStorage >= 5.2 and Refile >= 0.2.0 <= 0.4.0' do
with_form_for UserWithAttachment.build, :avatar
assert_select 'form input#user_with_attachment_avatar.file'
end

test 'builder generates file input for activestorage in Rails 5.2' do
with_form_for UserWithAttachment.build, :image
assert_select 'form input#user_with_attachment_image.file'
end

test 'builder generates file input for activestorage in Rails 5.2 with multiple files' do
with_form_for UserWithAttachment.build, :images
assert_select 'form input#user_with_attachment_images.file'
end

test 'builder generates file input for carrierwave' do
with_form_for UserWithAttachment.build, :photo
assert_select 'form input#user_with_attachment_photo.file'
end

test 'builder generates file input for carrierwave with multiple files' do
with_form_for UserWithAttachment.build, :photos
assert_select 'form input#user_with_attachment_photos.file'
end

test 'builder generates file input for paperclip' do
with_form_for UserWithAttachment.build, :portrait
assert_select 'form input#user_with_attachment_portrait.file'
test 'builder generates file input for Shrine >= 0.9.0, Refile >= 0.6.0 and CarrierWave >= 0.2.1' do
with_form_for UserWithAttachment.build, :cover
assert_select 'form input#user_with_attachment_cover.file'
end

test 'builder generates file input for refile' do
test 'builder generates file input for Refile >= 0.4.0 and Shrine >= 0.9.0' do
with_form_for UserWithAttachment.build, :profile_image
assert_select 'form input#user_with_attachment_profile_image.file'
end

test 'builder generates file input for refile with multiple files' do
with_form_for UserWithAttachment.build, :profile_images_files
assert_select 'form input#user_with_attachment_profile_images_files.file'
end

test 'builder generates file input for shrine' do
with_form_for UserWithAttachment.build, :cover
assert_select 'form input#user_with_attachment_cover.file'
test 'builder generates file input for Paperclip ~> 2.0' do
with_form_for UserWithAttachment.build, :portrait
assert_select 'form input#user_with_attachment_portrait.file'
end

test 'build generates select if a collection is given' do
Expand Down
28 changes: 6 additions & 22 deletions test/support/models.rb
Original file line number Diff line number Diff line change
Expand Up @@ -335,35 +335,19 @@ class UserNumber1And2 < User
end

class UserWithAttachment < User
def self.reflect_on_attachment(attachment)
OpenStruct.new if attachment == :avatar
end

def self.reflect_on_association(association)
OpenStruct.new if ["image_attachment", "images_attachments"].include?(association)
def avatar_attachment
OpenStruct.new
end

def photo_url
"/photos/1.png"
def cover_url
"/uploads/cover.png"
end

def photos_urls
["/photos/1.png", "/photos/2.png"]
def profile_image_attacher
OpenStruct.new
end

def portrait_file_name
"portrait.png"
end

def profile_image_attachment
OpenStruct.new
end

def profile_images_files_attachment_definition
OpenStruct.new
end

def cover_url
"/uploads/cover.png"
end
end

0 comments on commit a25950f

Please sign in to comment.