The musings of the Lunar Logic Polska team on Ruby, Rails, Merb, Flash, Flex, Adobe Air, agile, scrum, and any other buzzwords we can think of.

Our first iPhone app available on AppStore

by Jakub Suder, 3 March 2010

I became interested in iPhone development last winter, when I bought my own iPhone. I wanted to learn how to write iPhone apps, and the best way to learn how to program is to do it – so I needed to write a first simple application, that I could learn and experiment on. I've decided to write an iPhone client for our RubyTime service; I figured it would save me a few minutes each day if I could enter my activity entries while waiting for a bus on a bus stop instead of doing it in a hurry in the office before I leave (of course, I could also do it using mobile Safari, but it wouldn't be as convenient… and it wouldn't be so fun!).

The first version was ready a few months later – it was able to display recent activities and add new ones. I used and extended the JSON API that Marcin Kulik has earlier created when he was working on his RubyTime plasmoid for KDE4. I showed the app to Paul and he liked it so much that he allowed me to spend almost a month of my working time on improving it and adding new features. I've added support for admin accounts, to let Paul check on his iPhone who was busy and who wasn't, and for client accounts, so that our clients who have iPhones can monitor the progress of their projects. I've also added a search form that finds activities within a certain time range for given projects and users.

It took a bit longer than expected to bring the application to the point when it can be publicly released, also because we had to make sure that potential users can download a stable version of the server that supports the client app; but the release finally happened last month. I was surprised how fast the application went through the review process – I had heard stories of apps waiting for weeks or months to get accepted; mine was ready in less than 3 days!

If you want to try it, iRubyTime is available on the AppStore for free. I've also shared the source code of the app on GitHub, so if you're learning Cocoa and iPhone SDK, you can take a look at it and use it as an example or starting point for your own projects.

I must say that working on your first iPhone application is very difficult at first. It's a completely different experience than working on a Rails webapp – partially because of the language (ObjC), but also because of different approach and paradigms used in mobile app development, and because of limitations of the phone's hardware. I had to fix hundreds of strange and confusing bugs – but that means I've also learned a lot, and it will be easier next time.

iRubyTime screenshot

MySQL and MongoDB working together in Kanbanery

by John Cieslik-Bridgen, 15 February 2010

An important feature of the Kanban tool is the logging of project events, such as changes in task status, from which we generate the project history. I spoke with Marcin Kulik and Piotr Solnica about their decision to use MongoDB for this.

Several different solutions were considered initially, including:

  • logging to a text file
  • logging to the application's MySQL database
  • logging to a separate MySQL database
  • logging to a different database platform

The concern when making this decision was to make sure that the value of logging application events wasn't outweighed by any fall-off in performance, and having encountered MongoDB being used in similar contexts, it was investigated as a solution. We didn't need a transactional data-store - what we needed was fast reads and writes.

Once we started thinking of using MongoDB, we considered whether to use MongoMapper, which is akin to Active Record or DataMapper for MongoDB, built from scratch. But rather than use this, in the interests of consistency within our application, we opted for dm-mongo-adapter, a MongoDB DataMapper Adapter. Piotr Solnica is one of the authors of dm-mongo-adapter, and its current maintainer, so obviously we had unrivalled support for any issues we might encounter! So we were able to be more consistent in using the same abstraction library for development and testing, and whilst dm-mongo-adapter is not yet feature complete, it was sufficient for our purposes.

DataMapper allows you to work with multiple data-stores simultaneausly and have cross-database relations. We use this setup with MySQL and MongoDB right now. We've created a simple hierarchy of LoggedEvent models that are persisted in MongoDB and have them associated with other models from MySQL database. If you are wondering how you can achieve that, here is a simple example showing multiple repository setup in DataMapper:

We have a SingleTableInheritance setup with LoggedEvent as the base class and 3 other subclasses. Each of the subclasses has a set of additional properties that is specific only to them, not the base class. The big difference between MongoDB and MySQL in this case is the fact that the latter will store all the properties for each of the records resulting in a bigger database size and lower performance. For instance take a look at this example:

Notice that in MySQL we would have 8 columns whereas in MongoDB we only store the properties that are associated with specific model. That's why every record in the database has only 6 attributes. Another useful feature is Hash being the property type (:custom_attributes property in the above example). It's a flexible solution for storing meta-data that varies between records.

Piotr benchmarked inserts into a MySQL and a MongoDB using DataMapper and reported that inserts were more than 20x faster. Both he and Marcin pointed out that this is measuring the combined performance of the adapters and the database, and is not a test of each databases underlying speed.

Piotr's benchmarks seem to confirm that MongoDB and the dm-mongo-adapter were a good decision for logging application events in Kanbanery - the solution is very low impact, and one which we are very happy with.

My improvements on latest i18n gem

by Krzysztof Knapik, 13 January 2010

Originally published at knapo.net.

In recent weeks I spent a lot of time on i18n stuff in project I currently working on, so I was really happy, after I read José Valim’s article about new i18n gem, which has been very improved and introduces new features (Thanks José for great article and benchmarks).

Unfortunately, after few days of using it I noticed a few issues (which I reported on http://github.com/svenfuchs/i18n/issues. They were related to I18n::Backend::Fallbacks, which handled only translation method, and does not localize, pluralize and :default option, also I18n:Backend::Fast threw an exception when there were no translations for locale or one of locale fallbacks. Because I need all these 3 backends, they blocked using new i18n :(

Rather than wait until they will be fixed, I forked i18n http://github.com/knapo/i18n and fixed them by myself. So, I installed it as a plugin (using braid to easily upgrade its in future):

$ braid add -p git@github.com:knapo/i18n.git

And there’s a trick (which i18n’s README hopefully says about) – to use i18n as a plugin I had to add to my initializers/i18n.rb reload_i18n! method which replaces bundled i18n gem with plugin:

def reload_i18n!
  $:.grep(/i18n/).each { |path| $:.delete(path) }
  I18n::Backend.send :remove_const, "Simple" 
  $: << Rails.root.join('vendor/plugins/i18n/lib').to_s
end

reload_i18n!

and created my own backend (I preffer that than including all modules to I18::Backend::Simple)

module I18n
  module Backend
    class Knapo < Simple
      include I18n::Backend::Pluralization
      include I18n::Backend::Fallbacks
      include I18n::Backend::Fast
      include I18n::Backend::InterpolationCompiler
    end
  end
I18n.backend = I18n::Backend::Knapo.new

The only disadvantage of having i18n as a plugin is resetting I18n.load_path, so all default translations loaded by Rails are being removed, I mean:

actionpack-2.3.5/lib/action_view/locale/en.yml
activesupport-2.3.5/lib/active_support/locale/en.yml
activerecord-2.3.5/lib/active_record/locale/en.yml

But actually it might be a feature for some devs (e.g. me:) ), I copied them into my locales dir to active_support, active_record and action_view subdirs, and have all translations file in one place, and it’s better to have default (en) Rails ones there to easily compare other locale files with them, and/or edit them.

I also added extra extensions for I18n:

  • I18n::LoadPath which makes I18n.load_path more handy:
    I18n.load_path = I18n::LoadPath.new(I18n.load_path)
    I18n.load_path << Rails.root.join('locales/pl.yml') # loads single translation file
    I18n.load_path << Rails.root.join('locales') # loads all translation data files in specific directory
    I18n.load_path << Rails.root.join('locales/*.{yml,rb}') # loads all translation data files  by given pattern
  • I18n.wih_locale which executes block in given locale set
    I18n.with_locale("pl-PL") do
      # This code are being executed with pl-PL locale
    end
  • Making MissingTranslation message thrown by I18n.localize method complete, as previously when translation was missing it returned partial message e.g. for I18n.l Time.now, :format => :missing I was getting: translation missing: en, long_ordinal, what was misleading and now I’ve got: translation missing: en, time, formats, long_ordinal

The only thing I really don’t like in new i18n is forcing I18n.locale to Symbol – why? it should absolutely be a String

Anyway, thanks to Rails i18n team for great improvements on i18n, and looking forward for fixed issues in next gem version (and Rails3, of course).

Dev Talk on the Vodaphone mobile widget platform

by Paul Klipp, 4 November 2009

Maciej gave a presentation today based on his work creating mobile widgets for a client using the Vodaphone mobile widget platform. Here are the slides:

Lunar Logic Polska launches CodeRack global coding contest

by Paul Klipp, 9 October 2009

CodeRack is a coding contest dreamed up by a group of the Ruby programmers at Lunar Logic Polska who were excited about the possibilities of Rack middleware. The team wants to encourage Ruby developers to explore the possibilities and what better way than to hold a contest? The secondary goal of the contest is to generate a set of open source solutions that will solve real problems and inspire others. Every entry will be released under the MIT open source license.

Programmers are encouraged to submit contest entries that will be judged based on the cleverness of the application and the elegance of the code. Entries can be submitted at http://www.coderack.org until midnight EST November 15th. Finalists are scheduled to be announced on the 1st of December and public voting will run for one month. The final winners will be announced on the 5th of January.

The first round of the contest will be judged by an elite panel of judges including Ben Bangert of O'Reilly Media, Chris Wanstrath and PJ Hyett of GitHub, Joshua Peek of 37Signals, Yehuda Katz of Engine Yard and Rails core team member, Ryan Tomayko of Heroku, Core Rails team member Matt Aimonetti, and the Rails Envy team of Gregg Pollack and Jason Seifer.

Once the finalists have been selected by the panel, the public will vote for the top prize winners.

Prizes have been donated by Bytemark Hosting, GitHub, Jetbrains, Mindmeister, Freelance Total, Heroku, Rackspace Hosting, Peepcode, BDDCasts, and Zenbe Shareflow. The top prize includes a dedicated quad core server package and is valued at over $3000. Every entrant will receive a credit from bddcasts.com and $30 credit from Heroku. All finalists will receive a package including Zenbe Shareflow subscriptions, a RubyMine license from JetBrains, and five credits from bddcasts.com. Details of all of the prize packages will soon be available on the coderack.org website.

More information about the contest, including the contest rules, can be found at www.coderack.org.

What is Rack?

The Rack documentation describes it this way:

"Rack provides a minimal, modular and adaptable interface for developing web applications in Ruby. By wrapping HTTP requests and responses in the simplest way possible, it unifies and distills the API for web servers, web frameworks, and software in between (the so-called middleware) into a single method call."

© 2009 Lunar Logic Polska. All rights reserved.

Lunar Logic Polska is a proud member of: