Amazon Kindle for eBooks on a Jailbroken iPhone

Comments

Until November 25th Pragmatic Press is offering 40% off all their existing print and upcoming print books.  I took advantage of this and picked up a few print books, but one of the books I wanted was eBook only.  No problem, except… no Kindle.  So:

 

  1. Jailbreak iPhone if you haven’t done so already.  Very important to change your root and mobile user passwords – root’s password by default is `alpine’ - either by installing Cydia’s Terminal application or sshing into your phone.  (Jailbreaking is a time consuming process and I feel guilty about putting it as a single step.)
    1. You will need to install OpenSSH so you can copy files to the phone; you will probably also want to install Terminal.  Both of these applications are available for free within Cydia, just search for them and install.  It will take a long time for your very first ssh connection to your phone to connect as its generating encryption keys.
  2. Install the free Kindle app on the iPhone from the iTunes store.
    1. The Kindle stores its books in an `eBooks’ folder buried in the `/var/mobile/Applications/…/Documents/eBooks’ where the `…’ is a GUID identifying the application.
  3. SSH (preferably a client where you can copy and paste) or Terminal.
    find -type d /var/mobile/Applications -name 'eBooks'
    1. a. Copy the GUID, and you’ll want to end up with the path in 2.1, above, but where the `…’ is replaced by the GUID.  (On my device the GUID was 127DF7F1-9B49-423B-9FA9-77AB87775E24 but I don’t know if this is the same across devices; probably not.)
  4. This is purely for convenience, mainly because I want to use WinSCP to copy files from my Windows 7 PC to my iPhone and I don’t want to remember the GUID for the Amazon application every time I want to do this.  (You can also use command line scp, but you’ll likely still want to create a symlink.) (You may also want to use `/private/var/root/Media/eBooks’ if you prefer a better organizational hierarchy.)

    ln -s /var/mobile/Applications/YOUR_GUID/Documents/eBooks \
    /private/var/root/eBooks
  5. Now you can use WinSCP or scp to copy *.mobi files directly into your device’s `/private/var/root/eBooks’ directory; books you copy here will be available in the Amazon Kindle iPhone app next time you launch it.

Andy Hunt/Pragmatic Thinking and Learning Presentation @ RJUG

Comments

image I attended Andy Hunt's “Refactor Your Wetware: Pragmatic Thinking and Learning” presentation given for the Richmond Java User Group/Central VA Ruby User Group October meeting Wednesday night.  Having just completed this book in September I was very interested in reinforcing what I have learned (and began practicing, ahem, mind mapping) and excited to see the author present this material.

I was impressed with the professional atmosphere and organization at this event.

Andy’s presentation centered around the book, touching on several highlights over the two hour period.  This was largely a rehash for me, which was very good, with a little bit of new material thrown in.  (There is a new Pomodoro book pragprog is publishing so there was a brief overview of Pomodoro included with a plug – which I fully support at free/sponsored events; I had just read the RSS post earlier in the day so I would have been disappointed if it were skipped!)  His slides were good – not distracting – and the presentation was delivered with animation and some really well placed humor.

Points [I remember]:

Dreyfus Model of Skill Acquisition

Mind mapping (easily my favorite technique I learned from the book)

You cannot execute a great idea if you don’t exercise your brain to get it to produce them – write down your ideas, all of them

Meditation

How context switching and multitasking damages productivity

Have a personal wiki

Book study groups – going to suggest replacing our low value formal code reviews with this in an on-going basis

 

Finally Andy said it may be possible in the near future to get some of pragprog’s non-code books in an audio book format which for anyone who has a long commute is very good news.


I’m Dangerous with Ruby!

Comments

My solution was selected as the winning solution for RubyLearning.com’s RPCFN #2 “Average Arrival Time for A Flight.”

This challenge involved averaging times of the day without the actual day in the context.  When I first started to tackle the problem I thought to myself that this will be very easy.  Then I hit the “no day” context and realized that this problem was much tougher than I anticipated.  When I finally saw the posted solutions including Chris Strom’s (blog) it was like decades old high school math came rushing back to me.  I would have never thought of plotting points on a graph but now that I’ve been exposed I’m certain I will never forget it!

My friend [and commuting body] Matt and I talked through the problem during our drive home as we sat in Virginia I-495 outer loop and I-95S traffic.  He had some ideas about plotting the problem linearly around 0 but ultimately I ended up going with making assumptions about how close the provided times were to midday and midnight.

require 'time'

SECONDS_IN_DAY = 86400
MIDNIGHT = Time.parse("12:00AM").to_i
MIDDAY = Time.parse("12:00PM").to_i

def average_time_of_day(times)
  seconds = []
  times.each {|time| seconds << Time.parse(time).to_i}
  seconds.sort!
  if (seconds.first - MIDNIGHT) < (seconds.last - MIDDAY)
    seconds.map! {|s| s < MIDDAY ? s += SECONDS_IN_DAY : s }
  end
  Time.at(seconds.inject { |sum,n| sum += n }.to_f / seconds.length).strftime("%I:%M%p").downcase
end

 

Gist: https://gist.github.com/5b371226faf83af50d7e

Interview: http://rubylearning.com/blog/2009/10/22/charles-feduke-winner-rpcfn-2/


Temp Files and Ruby 1.8.6 on Windows

Comments

Working on the RPCFN: Shift Subtitle I found myself having to work with files input as a stream (or anyway that’s how I wanted to approach the problem; streams are efficient to me).  In order to give my code any sort of unit testing justice I needed to mock the file system.  The challenge expressly forbids any Ruby gems from being used in the script itself – and maybe by extension the unit tests as well – but I could not see devoting the time necessary to write a mocking framework for the file system.

I found a gem that does precisely what I needed named Construct.  Unfortunately there is a bug with Ruby 1.8.6 on Windows in regards to clean up of temp files.  The problem is that when attempting to clean up a Errno::EACCES is raised causing the unit test to fail (or you to write a lot of rescue blocks).

A workaround I came up with was to replace the rmtree method in the Pathname class within my unit test to perform no clean up.  Not the best approach I am sure, but it let me get on with my work.

# something_test.rb
require "test/unit"
require 'construct'
require 'something'

class Pathname
  # windows has problems with temp files created by Ruby
  # http://redmine.ruby-lang.org/issues/show/1494
  def rmtree
    nil
  end
end

class SomethingTest < Test::Unit::TestCase
   # test methods...
end

Ruby: Mocking Kernel Exit

Comments

I’m working on the RubyLearning blog’s Ruby Programming Challenge for Newbies #1 to learn the language – I’ve done a bit with Rails and some admin scripts so I could use the exposure.  Since I love TDD approaching Ruby development through RSpec is only natural, but it was a pain in the ass trying to find how I could have RSpec verify that my program properly exited when certain conditions were met.  Here’s how I solved it, reposted here:

# something.rb
class Something
    def initialize(kernel=Kernel)
        @kernel = kernel
    end

    def process_arguments(args)
        @kernel.exit
    end
end

# something_spec.rb
require 'something'
describe Something do
    before :each do
        @mock_kernel = mock(Kernel)
        @mock_kernel.stub!(:exit)
    end

    it "should exit cleanly" do
        s = Something.new(@mock_kernel)
        @mock_kernel.should_receive(:exit)
        s.process_arguments(["-h"])
    end
end

What I learned was that you can define a constructor with optional arguments (in this case, initialize(kernel=Kernel) and then proceed to use @kernel’s methods instead of the methods that Kernel provides when you do not specify a class instance.  With a properly mocked and stubbed exit method in my spec things operate as expected.