This allows users to upload an file from the browser into my Rails app using the paperclip gem. Once the file is uploaded it gets saved into the filesystem. When the user then goes in and the "show" method or the "edit" method is evoked the image is shown to the user. This is fine for image files but for .csv and .txt files I don't want to show the preview in the browser. This code is clunky and I know there is a better way to do this.
<% if @user.image? %>
<%=filetype = @user.image.url %><br/>
<%if filetype.include? ".jpeg" %>
<b>isJpeg</b>
<%= image_tag @user.image.url %> <br />
<%= link_to @user.image.url, @user.image.url %>
<% end %>
<%if filetype.include? ".gif" %>
<b>isGif</b>
<%= image_tag @user.image.url %> <br />
<%= link_to @user.image.url, @user.image.url %>
<% end %>
<%if filetype.include? ".png" %>
<b>isPNG</b>
<%= image_tag @user.image.url %> <br />
<%= link_to @user.image.url, @user.image.url %>
<% end %>
<%if filetype.include? ".jpg" %>
<b>isJPG</b>
<%= image_tag @user.image.url %> <br />
<%= link_to @user.image.url, @user.image.url %>
<% end %>
<%if filetype.include? ".csv" %>
<b>isCSV</b>
<p>Your file was a csv file and has no preview</p>
<%= link_to @user.image.url, @user.image.url %>
<% end %>
<%= image_tag @user.image.url %> <br />
<%= link_to @user.image.url, @user.image.url %>
<% end %>
-
1\$\begingroup\$ write a helper that returns a string given a filetype (isJPG, isPNG, ...). \$\endgroup\$tokland– tokland2012年04月29日 18:26:19 +00:00Commented Apr 29, 2012 at 18:26
2 Answers 2
tokland is right (on both counts), you should push all that logic into a helper. You can also add a bit of OpenStruct into the mix to make the helper nicer:
# in app/helpers/application_helper.rb or another helper
def user_image_info(user)
info = OpenStruct.new(:has_image? => false)
return info if(!user.image?)
# There might be better ways to do this but I don't know paperclip.
u = user.image.url
%w[jpeg gif png jpg csv].find do |ext|
# A small abuse of `find` but reasonable in this case.
info.is = "is#{ext.upcase}" if(u.include?(".#{ext}"))
end
if(info.is == 'isCSV')
info.preview_link = '<p>Your file was a csv file and has no preview</p>'.html_safe
else
info.preview_link = (image_tag(user.image.url) + '<br>').html_safe
end
info
end
Then in your ERB, you could do something like this:
<% info = user_image_info(@user) %>
<% if info.has_image? %>
<b><%= info.is %></b>
<%= info.preview_link %>
<%= link_to @user.image.url, @user.image.url %>
<% end %>
I'd use some kind of presenter here. Or exhibit (see Objects on Rails). So some object where you can extract your view logic.
# replace you view with these 2 lines of code
<% @user = UserExhibit.new(user, view) %>
<%= @user.render %>
class UserExhibit < SimpleDelegator
def initialize(user, context)
@context = context
super(user)
end
def render
return '' unless @user.image?
@context.render partial: "user_image", locals: { user: self }
end
def filetype
image.url
end
def image_is_picture?
filetype =~ /\.(jpeg|gif|png|jpg)$/
end
def image_type
filetype[/\.(\w+)$/, 1]
end
end
# _user_image.html.erb partial
<b>is<%= @user.image_type.upcase %></b>
<%if @user.image_is_picture? %>
<%= image_tag @user.image.url %> <br/>
<%= link_to @user.image.url, @user.image.url %>
<% else %>
<p>Your file was a <%= @user.image_type %> file and has no preview</p>
<%= link_to @user.image.url, @user.image.url %>
<% end %>
<%= image_tag @user.image.url %> <br/>
<%= link_to @user.image.url, @user.image.url %>
Also, you may find useful these links: