We ♥ web applications!
At mobalean we love to build innovative web services for Japan and the world. Our experience will help transform your ideas into successful online services.
At mobalean we love to build innovative web services for Japan and the world. Our experience will help transform your ideas into successful online services.
Mobalean is lead by Henri Servomaa, the original founder and mobile developer. At Mobalean we strive to develop services which are loved by our clients and users. By working in an agile manner, quickly adapting to changing requirements, we can deliver quickly and often.
Hailing from Finland, Henri has a long history with computers and the internet. With a background in Electrical Engineering and Computer Science, he has worked in Japan as Software Developer and System Admin since 2001. In 2005, he joined a company to develop mobile sites for the Japanese market and has been involved in mobile ever since.
Cleve Lendon is a Canadian engineer who has been contracting for Mobalean. He came to Tokyo in 1994, and has lived here ever since. He has broad experience as a software developer, which includes development of mainframe software, Internet applications and mobile apps (Android and iOS). He is especially skilled at writing Java applications (vd. Simredo 4, Grafikilo 15). When not programming, Cleve enjoys improv acting and studying languages, such as Latin and Esperanto.
Our strength is crafting web services for both Japanese and international markets. We bring our technical and cultural experience to help you adapt your ideas into successful products.
We develop with Ruby on Rails and use the best agile practices and tools, such as test driven development and continuous integration to achieve quality.
We are the leading provider of technical expertise about the Japanese mobile web. Mobalean started when the smartphones were just appearing on the market. Our Keitai Web Technology Guide is a quick starting point for learning about the initial challenges of Japanese mobile development. Although the technology stacks have changed since the proliferation of iOS and Android, some of the idiosyncrasies remain. Most notably, the Japanese market is still very much dominated by the big three carriers: DoCoMo, au and Softbank. Developers can find more technical details in our Keitai-Dev Wiki.
Email address: info@mobalean.com
If you prefer to call us, feel free to do so under +81 (0)70-6251-7245
For users of Skype, please call mobalean
One of our projects is an upgrade of old Ruby code (version 1.8.6, 2007) to modern Ruby. It's a fairly large, non-rails project that has been developed for the Japanese market during many years. This article discusses the main issues we came across. Perhaps it will be useful to others who need to do the same. The reader should be familiar with Ruby, and tools such as irb.
One of the biggest changes since version 1.8 is the way in which character encodings are handled.
In Ruby 1.8, a String has no intrinsic character encoding; it's handled as a sequence of bytes. The global variable \$KCODE is used to define the default encoding for regular expression matching. We usually see \$KCODE set at the top of a file:
\$KCODE='UTF8'
Valid values are 'UTF8', 'SJIS', 'EUC' and 'NONE', but the first letter of the encoding is sufficient.
\$KCODE was deprecated in Ruby 1.9 (2007), so we removed it from the code.
Since Ruby 1.9, 'encoding' has become an attribute of the String class, and the default encoding is UTF-8, as God intended.
"Hi".encoding => #<Encoding:UTF-8>
When we run old code under Ruby 2.3, Strings which previously had no encoding become UTF-8 by default. This causes encoding errors if the string is actually a Shift JIS string. We can correct this using the 'force_encoding' method.
new_string = some_string.force_encoding('SJIS')
'force_encoding' doesn't change the characters in the string. It simply sets the 'encoding' attribute.
In our legacy code, the gem 'iconv' is often used to convert between character encodings. The example below converts the text 'コメント' from UTF-8 to Shift JIS.
require "iconv" comment_sjis = Iconv.iconv('Shift_JIS', 'UTF-8', 'コメント')
Iconv was deprecated in Ruby 1.9. Strings are now converted using 'encode':
comment_sjis = 'コメント'.encode('SJIS')
Or, to ensure that the original string is treated as UTF-8:
comment_sjis = some_string.force_encoding('UTF-8').encode('SJIS')
The Array#to_s (to string) method has given us a lot of trouble. In 1.8, to_s was used to concatenate the contents of an array.
['A', '5'].to_s => "A5"
Since Ruby 1.9, this now returns a different result:
['A', '5'].to_s => "[\\"A\\", \\"5\\"]"
This is the same output as Array#inspect.
In modern Ruby, array contents should be concatenated by using the 'join' method:
['A', '5'].join => "A5"
By the way, 'join' can take a separator as a parameter:
['A', '5'].join(', ') => "A, 5"
In Ruby 1.8, the class method 'instance_variables' returns an array of strings which represent instance variables. For example, this code:
class Weather @temperature = "cold" @rain = "probably" end puts "Instance variables: #{Weather.instance_variables}"
...outputs:
Instance variables: @rain@temperature
Since version 1.9, 'instance_variables' returns an array of symbols:
Instance variables: [:@temperature, :@rain]
In new code, we test for the existance of instance variables with symbols.
This:
if Weather.instance_variables.include?('@temperature')
becomes:
if Weather.instance_variables.include?(:@temperature)
In our legacy code, the module 'parsedate' was used to parse string representations of dates.
require 'parsedate' ParseDate.parsedate("Tuesday, November 29th, 2016, 18:53:01 JST", true) => [2016, 11, 29, 18, 53, 1, "JST", 2]
Like so many other things, parsedate was deprecated in Ruby 1.9.
The Time class has a parse method. Time is built into Ruby; normally, you don't need to require it, but it is necessary to require 'time' in order to use the parse method.
require 'time' Time.parse("Tuesday, November 29th, 2016, 18:53:01 JST") => 2016-11-29 18:53:01 +0900
Date and DateTime can also be used to parse strings. For information on the differences between these classes, please refer to: http://stevenyue.com/blogs/date-time-datetime-in-ruby-and-rails/
Every Ruby object has a unique identifier. In Ruby 1.8 this was Object#id, but 'id' was later deprecated and replaced with 'object_id'. The compiler prints out deprecation warnings, so this shouldn't be hard to fix, but as Captian Hunt always says, "It's never easy."
There is a technique for creating test cases called 'mocking'. If we have a class X, which we want to test, and class X processes data which it gets from class Y, we can 'mock' class Y. That is, we create a class which looks like Y, but returns values which we define for our test.
There are libraries which facilitate this. Some of our legacy code used Test-Unit-Mock, which was written before object_id existed. Test-Unit-Mock treated Object#object_id as an ordinary method, and 'mocked' it, which caused problems for some of our test cases.
For writing unit tests with mocking, I recommend using Flexmock:
http://github.com/jimweirich/flexmock
'Circular requires' occur when a Ruby file 'requires' files which in turn require the original file. For example, consider a file called Parent.rb, containing a class called Parent. There are child classes, ChildA, ChildB etc., which refer to Parent, because they are descended from it:
require './Parent' class ChildA < Parent
If the Parent file requires the child classes, for example:
class Parent ... end Dir.glob("#{File.dirname(__FILE__)}/Child*.rb").each do |file| require file end
...then you have circular requires.
Ruby 1.8 gives no warning of circular requires, but later versions do, if warnings are enabled (with the -w flag):
.../2.3.0/rubygems/core_ext/kernel_require.rb:55: warning: loading in progress, circular require considered harmful - /Users/cleve/temp/Parent.rb
Why are circular requires considered harmful? There is a good discussion of the issues here:
http://stackoverflow.com/questions/1897537/why-are-circular-references-considered-harmful
The Parent/Child example shown above is artificial; it seems unlikely that a developer would intentionally write such code. But in large, complex systems, which have evolved over a number of years, the relationships between classes can become obscurred. Developers put in circular requires unintentionally.
When we started running our old source under 2.3, with warnings enabled as they should be, a *lot* of circular requires popped up.
Cleaning up these warnings was sometimes easy, and sometimes very difficult. In some cases we could just delete an unnecessary require. In other cases we had to refactor a file. Splitting a single file into two separate files, with different requires, sometimes solved the problem. A few times, with very tangled code, we used the c-header method of defining a variable and checking it for require'ing like this:
require 'BaseDBClass' unless defined?(BASEDBCLASS)
I hope this article has been helpful to those who need to modernize ancient code.
If you have any comments or suggestions, please contact us.