Entries from June 2008 ↓
June 24th, 2008 — pagination, ruby on rails, tips and tricks
I want my list of data to be paginated by letters. The will_paginate plugin certainly gives excellent pagination if all you want is “prev 1 2 3 .. 6 next” kind of pagination.
However what if you’re looking for entries that start with the letter H and you have no idea if that’s page 4 or page 42? You’re probably wanting something more like “# A B C D…” pagination.
I did some googling and found people speaking of solutions for “A B C D…” but in my case, not all of my entries start with letters! If you have something like media titles in your data set, having an entry start with a number is perfectly normal. Some might even start with special characters! Some people suggest having an ‘All’ option, but if you need pagination, it’s probably because you have enough data that showing all options at once is a very bad idea.
Here’s my solution:
First I make a helper function for my options that’ll be cached permanently.
def letter_options
$letter_options_list ||= ['#'].concat(("A".."Z").to_a)
end
Here’s my index action in my controller:
@letter = params[:letter].blank? ? 'a' : params[:letter]
if params[:letter] == '#'
@data = Model.find(:all, :conditions => ["title REGEXP ?",
"^[^a-z]"], :order => 'title', :select => "id, title")
else
@data = Model.find(:all, :conditions => ["title LIKE ?",
"#{params[:letter]}%"], :order => 'title', :select => "id, title")
end
Here’s my html
<div class ="pagination">
<% letter_options.each do |letter| %>
<% if params[:letter] == letter %>
<span class="current"><%= letter %></span>
<% else %>
<%= link_to letter, staff_games_path(:letter => letter)%>
<% end %>
<% end %>
</div>
There we go! Now the # will pull up all entries where the first character is not a letter.
June 19th, 2008 — attachment fu, mime types, rubyzip, zip
Today I’m going to share how you can let your app accept zip files which will then be extracted into multiple attachments. If you already use Attachment Fu to manage files, this should be super easy to add.
Before my controller had something like this:
Attachment.create(:uploaded_data => params[:Filedata])
First break that up into something more like this:
attachment = Attachment.new
attachment.uploaded_data = params[:Filedata]
attachment.save
Then put in some split logic for if it’s a zip file:
attachment = Attachment.new
attachment.uploaded_data = params[:Filedata]
if attachment.content_type == "application/zip"
# Unzip this and process all the inner files
Attachment.build_from_zip(attachment)
else
attachment.save
end
Now we’ll need the RubyZip gem and MIME Types gem, so do:
sudo gem install rubyzip
sudo gem install mime-types
Now in the Attachment
class we’ll add the build_from_zip
method:
def self.build_from_zip(ss)
zipfile = Zip::ZipFile.open(ss.temp_path)
zipfile.each do |entry|
if entry.directory?
next
elsif entry.name.include?("/")
next
else
screen = Attachment.new
screen.filename = entry.name
screen.temp_data = zipfile.read(entry.name)
mime = MIME::Types.type_for(entry.name)[0]
screen.content_type = mime.content_type unless mime.blank?
screen.save
end
end
end
The only two non-obvious things to note here are:
- I skip the files with / in them because when I archive files on my machine, hidden files with / characters in them make it into the archive. I only want the real files.
- I use the MIME Types gem to decide the content type from the filename.
I hope you find this helpful, enjoy!