Skip to content

Compress Rails project images

We were having some issues with slow loading times on our site, so I set out to compress all of our uploaded images.  Since we have thousands of images doing it by hand is not really an option, and plenty of the images are transparent PNGs.  So I enlisted the help of TinyPNG.

TinyPNG is an online application that compresses both PNG and JPG images, and preserves the alpha layer for PNG images, and it offers an API along with a ruby gem.  So you can use it to automate compressing images.  First start by installing the gem, and I also use the fastimage gem for this script so if you don’t have it install that too.

1
2
3
gem install tinify
gem install fastimage
rbenv rehash (if you're using rbenv)

Now you just need the script below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
require "tinify"
require 'fastimage'
Tinify.key = "YOUR API KEY"
 
i = 0
Dir.glob("public/system/rich/rich_files/rich_files/**/*.{jpg,png}") do |item|
  #only do 50 images at a time
  break if i == 10
 
  #ignorre directories and original files
  next if item == '.' or item == '..' or item.include? "original"
 
  #ignore iamges less than 50KB
  filesize = (File.size(item) * 0.001).floor
  next if filesize < 50
 
  #ignore images that are smaller thatn 100KB and over 600px large
  size = (FastImage.size(item).inject(:+))
  next if size >= 600 and filesize < 100
  i = i + 1
 
  source = Tinify.from_file(item)
  source.to_file(item)
 
  new_filesize = (File.size(item) * 0.001).floor
 
  puts "Converted: #{item}"
  puts "Original: #{filesize} Optimized #{new_filesize}"
end
 
puts "All done!"

Some things you’ll need to address to get this working are first, swap out “YOUR API KEY” with your actual API key, you can get one here. And if you’re not using the rich gem to handle image uploads you’ll need to change “public/system/rich/rich_files/rich_files” to whatever the location of your images is. The “**/*” part of the path will search all sub-directories and files in those sub-directories, and “.{jpg,png}” will only search jpg and png images.

The code will go through all the JPG and PNG files in your images directory, it will ignore all original versions, and then ignore files that are too small to bother with and then print out the files that were compressed along with their original and optimized sizes, then print out “All done!” once it’s finished.

Save it as tinify.rb and you can run it in the console with:

1
ruby tinify.rb

This will process 50 images at a time, and ignore images that I’ve set as too low to both with, so all images under 50KB are ignored, and images over 600x600px and lower than 100KB are ignored.  But this does pose a problem – images that aren’t reduced enough will still get re-reduced if you run the script multiple times.  For now I’m just monitoring it, and I’ll adjust it if too many images get caught.

Meal Replacement Bread Recipe ver 3

It’s time again to make some changes to my shake recipe, but it’s no longer a shake recipe!  As I’ve changed it so now I’m using it to bake bread 🙂  I was looking at the recipe…and it seemed to be getting weirder and weirder for a shake recipe, but after a little research I found it was perfect for a bread recipe!  It has various ingredients that are flour replacements, an egg, and applesauce is a apparently a good replacement for butter. So really the only difference is how I cook it.

So the changes to make this into bread are to ground up the apples into apple sauce and then cook it in the microwave for 5 minutes and that’s about it 🙂  To make sure it stays moist you need to put a cup of water in with it in the microwave. You can also add in some baking powder to make it nice and fluffy.

With this new version I’m looking to remove carbs from the recipe and bad macros to make it more healthy and better for weight loss.  I wrote up an article in the past on macro-nutrients which is my basis for making these changes.  I’m also changing back to Optimum Nutrition protein powder so it tastes a lot better :X  It does make it a bit more expensive, but I’m getting too tired of the chalky rice protein.

IngredientCarbsProteinFatFiberCalories$$/servingAmazon
Optimum Nutrition Protein3241.501201.07Buy
bob's flaxseed meal533.54600.11Buy
hooster powdered egg162.5800.56Buy
Dried Apple Rings (1/2 serving)15.502.5600.25Buy
bob's pea meal 9404500.02Buy
bob's almond meal (1/2 serving)3371.5400.21Buy
Totals3642.514.5124902.21

Bad Macros, before/after

  • 2/3 sat fat
  • 28/15.5 Sugar
  • 225/same cholesterol

At this point I think I’ve lost all faith in Fooducate so I’m removing it.  After finding this review of dymatise protein and this review of the same exact product.  I looked over the nutrition facts and ingredients, and they’re identical.  The image of the product as well.  So why is one entry a C and the other a B???  I have made thoughts of my making my own food rating system that’s completely automatic, and seeing results like these show up in fooducate make me think their more human method just isn’t that reliable.  One result that’s really vexed me on there is how they can give Tina’s Burritos a B, I just can’t believe that a .80 frozen burrito is better for you than protein powder.

I’m also considering ordering some Citrus aurantium powder, since it contains Synpehrine which is an active ingredient in Shred JYM.  And I’m also thinking about trying lemon peel and peppermint.

  1. Orange peel
  2. Lemon peel
  3. Peppermint

So my recommended spices would end up something like this:

  1. Cinnamon
  2. Matcha Powder
  3. Licorice Root
  4. Chia Seeds
  5. Orange Peel
  6. Lemon Peel
  7. Peppermint

But I’m thinking of saving that for the next round, at this point I’m feeling like there’s not a lot of more advancements I can make while sticking to my original goals.  To make it better for weight loss I’d need to remove more carbs, but all the carbs are from the fruit and vegetable ingredients – which having those was kind of the whole point in the first place. The only ingredient in here that’s not an appetite suppressant is the pea meal, but after doing a lot of research there’s not many vegetables that are as low carb as the pea flower and none that are as cheap.  So I might be reaching a final version 🙂

Simple reference for creating a Rails migration

I keep forgetting the rails generator syntax for migrations :X  I can never find just a quick easy guide for it – so I thought I’d write one up!

Instructions

  1. cd …
    obviously first make sure your in the main project folder in the console
  2. export RAILS_ENV=environment
    Also, make sure you’re in the right environment, you will probably want to make the change first in your test or development environment and then put it to production
  3. rails g migration AddColumnToModel column_name:column_type
    Here’s the main part, on  older versions rails g migration will be script/generate migration.  The “AddColumnToModel” syntax is important and should relate to the migration you’re making like “AddEmailToUser” and then at the end you can add a “column_name:column_type” reference for each column you want to add, for instance with the last example you would put “email:string
  4. rake db:migrate
    run the migration and add those columns to the database!  You’ll probably want to review the migration that was generated first though – it’ll be the latest file in the …/db/migrate directory

AND MAKE SURE TO RESTART YOUR SERVER AFTER MAKING A CHANGE

Column Types

  • binary: for files/ data blob
  • boolean: true/false
  • date: only date: (year, month, day)
  • datetime: date + time
  • decimal: precise decimal numbers – for when math neds to be accurate
  • float: decimal numbers
  • integer: whole numbers
  • string: 255 max alphanumeric characters
  • text: unlimited alphanumeric characters
  • time: only time (hours, minutes, seconds)
  • timestamp: same as datetime

 

And, if you make a mistake a quick way to go back and fix it is “rake db:migrate:redo” that will undo your last change, and re-run it.

Also, if you want to only run “rake db:migrate:up VERSION=20090408054532”

In a pinch you can also run a migration by hand in the console with the following format:
ActiveRecord::Migration.add_column :table, :column_name, :column_type

References:
http://stackoverflow.com/questions/11889048/is-there-documentation-for-the-rails-column-types
http://stackoverflow.com/questions/15162055/rails-generate-migration
http://stackoverflow.com/questions/7694487/ruby-on-rails-how-can-i-revert-a-migration-with-rake-dbmigrate

Japanese Regex

I was formatting a list of words from Tanos to a CSV document to import as a deck on my site SRS-Ninja.  Which is something I’ve done before, but this time to make it even easier to format, I found out you can use regular expressions on Japanese!  I found a nice guide on Github which goes over a lot of the possible variations. In this post I wanted to highlight a few I found specially helpful.

  • Kana alone = ([ぁ-ゔゞァ-・ヽヾ゛゜ー])
  • Kanji alone = ([一-龯])
  • Kanji and Kana = ([一-龯ぁ-ゔゞァ-・ヽヾ゛゜ー])
  • Half width numbers + roman characters = ([0-9A-z])

I didn’t need the half width ones for this particular task, but I hate how those sneak in when you’re writing in Japanese and English and I love that I can now flush those out!

Also on a more random note, I wanted to put a reminder here for myself on how Dreamweaver wildcards work. Laugh if you will, but Dreamweaver has a very powerful find and replace feature and has been the easiest way I’ve tried to convert HTML tables to CSV files. So, in short, you would put your regex in the find box as say “before ([0-9A-z]+) after” then in replace box you can use a $1 to return whatever text you found like “new before $1 new after”. So, something like this:

Screenshot (90)

iDrive makes signing up fun

This is just a small aside, but something I really wanted to point out.  When signing up for iDrive they’re form was surprising fun!  A cute example of how you can easily make you’re site a bit more pleasant and engaging 🙂

idrive_signup