Automatically reduce image sizes with smushit

UPDATE: lossless image size reduction of whole folders

smushit.com reduces image sizes dramatically, lossless!
Great for logos/icons…, but does not work for gifs!

I put together a small script to automate smushing (as long as i cannot find a popper API).

Usage
ruby smush.rb http://my.file.com/123.png where/to/save.png

Install
requires ruby and rubygems

sudo gem install json

Store this into smush.rb

optional(if this task is to full/gets blocked):
cange the &task=89266837334214400 to something else or use random

#smush.rb
def store_smushed_image(url,file)
  File.open(file,'w') do |f|
    f.puts smushed_image_data_for(url)
  end
end

def smushed_image_data_for(url)
  require 'cgi'
  url = CGI.escape url
  
  require 'net/http'
  require 'rubygems'
  require 'json'
  
  http = Net::HTTP.new('smushit.com')
  path = "/ws.php?img=#{url}&task=89266837334214400&id=paste2"
  
  resp, data = http.get(path, nil)
  raise "oops #{resp}" unless resp.is_a? Net::HTTPOK
  
  path = "/#{JSON.parse(data)['dest']}"
  resp, data = http.get(path, nil)
  data
end

#http://smushit.com/ws.php?img=http%3A%2F%2Fwww.famfamfam.com%2Flab%2Ficons%2Fsilk%2Ficons%2Fdrink_empty.png&task=89266837334214400&id=paste2
url = ARGV[0] || "http://www.famfamfam.com/lab/icons/silk/icons/drink_empty.png"
file = ARGV[1] || 'out.png'
store_smushed_image(url,file)

Enhanced RSpec Profiling

If normal rspec profile output is not enought, try this enhanced rspec profile formatter!

Example

Groups:
5.1150300 Movie
4.9603220 Icon
1.7279670 User
1.4466160 Person
...

Single examples:
4.8707710 Icon refresh! resizes existing thumbs
0.9086340 Review releases the movie
0.5203390 Movie finds invalid
...

Install

script/plugin install script/plugin install git://github.com/grosser/rspec_enhanced_profile.git

#add to spec/spec.opts:
--format RspecEnhancedProfile:tmp/profile.txt

Record Gettext at Test Runtime

Recently our team got frustrated with all the phrases gettext would not find.

  • words in if blocks
  • word produced by helpers
  • words used in arrays that get translated at runtime

Here is a simple solution: collect all phrases that were used during testing. Since the testsuite often has  100% C0 coverage and any phrase that is not found will signals missing tests.

Install

#spec/spec_helper.rb or test/test_helper.rb
if ENV['LOG_GETTEXT']
  def _(word)
    File.open(ENV['LOG_GETTEXT'], File::WRONLY|File::APPEND|File::CREAT) do |f|
      f.puts word
    end
    gettext(word)
  end
end


#lib/taskts/gettext_test_log.rb
task :gettext_test_log do
  tmpfile = 'locale/tmp_gettext_test_log.txt'
  outfile = "app/testlog_phrases.rb"
  
#  system "rake test LOG_GETTEXT=#{tmpfile}"
  system "rake spec LOG_GETTEXT=#{tmpfile}"
  process_log(tmpfile,outfile)
end

def process_log(tmpfile,outfile)
  found = {}
  File.readlines(tmpfile).each do |line|
    line.strip!
    next if line.empty?
    next if line =~ /%s of /
    next if %w[nil Sun Mon Tue Wed Thu Fri Sat Sunday Monday Tuesday Wednesday Thursday  Friday  Saturday  Jan Feb Mar  Apr Jun  Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December].include? line
    found[line]=true
  end
  
  File.open(outfile,'w') do |f|
    found.each do |k,v|
      f.puts "_('#{k}')"
    end
  end
end

Usage
The generated testlog_phrases.rb should be placed in a folder that is search by your updatepo task(it is not meant to be executed).

Custom Form Builders Are Evil

Every Formbuilder i see does the same, building some rows/tables/div structure around the fields it is be called on.

f.text_field => tr td label input

In theory this sounds great, but as soon as one tries to make some real life use of it it breaks down:

  • How do i handle I18N ?
  • How can i change the label text from the default
  • How do i put the checkbox in front of the label
  • How can i output only a field/2 fields in one row

Form builders that always output label+input are unsuited for everyday development!

So what else can we do ?

#app/helpers/application_helper.rb
class ActionView::Helpers::FormBuilder
  def build_translated_label(content)
    if content.class == Array
      label(content[0],content[1])#label + text
    elsif content.class == String
      label('',content)#text
    else content.class == Symbol
      #uses gettext translation, feel free to insert your own...
      label(content,_("#{object.class}|#{content.to_s.capitalize.gsub('_',' ')}"))#label + translation        
    end
  end
  
  def row(label,content)
    @template.content_tag('div',build_translated_label(label) + content.to_s,:class=>'row')
  end
end

Usage

f.row(_('Movie|Website')+'http://', f.text_field(:website))
f.row(:tags, f.text_field(:tag_list)+_('comma divided'))

If someone wants the R-specs, drop me a mail 🙂

Small Spec Helpers

So small but so powerful, i just wanted to share my little time savers, and hope you share your most essential helpers in the comments.

(I use @item as an alias for the current object in all my tests, to make generic tests less painful.)

Small example:

it "renders feedback" do
  expects_find
  get :feedback , :id => @item.to_param
  response.should render_template('edit')
end

Code:

#spec/spec_helper.rb
def mock_create(item,success,para=nil)
  if para
    item.class.expects(:new).with(para).returns item
  else
    item.class.expects(:new).returns item
  end
  item.expects(:save).returns success
end

def mock_update(item,success)
  expects_find(item)
  item.expects(:save).returns success
end

def expects_find(item=nil)
  item ||= @item
  item.class.expects(:find).with(item.to_param).returns(item)
end