Building an application to track expenses in one hour using GeoChat
Whenever one of our team member travels to another country we tell her to track expenses like food, transportation and accomodation so that later that money can be refunded. Each of us does it in a different way: we write it in a notes application in a cellphone, or in a text file in our computer, or maybe in a web application. The problem with the two first approaches is that the information might be lost: the machine might crash or be lost. The last approach is ok, but then you need to remember to connect to the internet to track the expense, and that can happen several hours after having paid, and our memory is not very good.
So I wanted to simply send an sms message to some number to track my expenses. I carry my cellphone all the time so I can send an sms immediately after paying something. Such an application seems very hard to do at first, specially because of the messaging component: receiving sms, configuring a number, etc. Doesn’t it?
Well, we have GeoChat! GeoChat is an application that lets you create groups of people to stay in touch with them. When a message is sent to a group it will be broadcasted to every member. And not necessarily to their mobile phone: each user can decide to receive emails, twitter updates, an instant message to their jabber client, etc. The original use case is for people in the field to report emergency and disaster situations to recover from them as quickly as possible. But that doesn’t mean we can use it for other purposes.
For example, one thing that you can do is configure a group in GeoChat to forward some or all of the messages to an external service. You can also configure GeoChat not to broadcast its messages.
So here’s the idea: we’ll create a group and we’ll configure it to send every message to an external service. This service will receive messages like “shopping $20″ or “accomodation $300″.
So I started coding it and in one hour I got it working! This new tool is called Xpenz.
That shows us how easy is to build some applications on top of GeoChat. In fact, here we are not using much of GeoChat’s power, mainly the messaging component. For this you could instead use Nuntium, but I decided to use GeoChat since a lot of messaging is already configured for me and I also had the authentication problem solved.
The code is in Google Code, so it’s open source. Let’s review the main logic:
class TrackController < ApplicationController
def expense
name = params[:sender]
if name.blank?
head 'bad_request'
else
User.track :user => name, :message => request.raw_post
head 'ok'
end
end
end
So basically we are getting the sender query parameter, which is the GeoChat login name, and if it is present we track the expense by using the request raw post body. And here’s User#track:
def self.track(options)
user = User.find_or_create_by_name options[:user]
pieces = options[:message].split(' ')
pieces.map!{|x| x.start_with?('$') ? x[1 .. -1] : x}
numbers = pieces.select{|x| x.float?}
texts = pieces.select{|x| !x.float?}
text = texts.join(' ')
if numbers.length == 0
user.currency = text
user.save!
else
if numbers.length == 1
amount = numbers[0].to_f
else
amount = numbers.last
numbers[0 .. -2].reverse.each{|n| text = "#{n} #{text}"}
end
Expense.create! :user => user, :amount => amount, :reason => text, :currency => user.currency
end
end
So the first line finds or create the user in xpenz for the GeoChat user. Then we split the message in spaces and do some logic do termine whether it’s a currency change or an expense track.
The main point here is that I just had to write about 20 lines of code to make it work. Well, maybe 50 because I tested it.
Quick way to test many values in ruby
Many times we end up having similar tests: same logic but different inputs and expected outputs. For example, suppose we need to test our brand new sqrt function:
test "sqrt 1" do assert_equals 1, sqrt(1) end test "sqrt 4" do assert_equals 2, sqrt(4) end test "sqrt 9" do assert_equals 3, sqrt(9) end
Here we are dupplicating code, since “assert_equals X, sqrt(Y)” is written all over the place. The naive way to refactor this is:
def assert_sqrt(input, output) assert_equals output, sqrt(input) end test "sqrt 1" do assert_sqrt 1, 1 end test "sqrt 4" do assert_sqrt 4, 2 end test "sqrt 9" do assert_sqrt 9, 3 end
Much better.
Some languages provide tools to deal with this problem in a nicer way. In C# you can do this:
[Test]
public void TestSqrt(
Values(
new int[] { 1, 1 },
new int[] { 4, 2 },
new int[] { 9, 3 }
) int[] values) {
Assert.Equals(values[1], Sqrt(values[0]));
}
So here we are supplying a set of values for our test. (maybe not much nicer, but the code duplication is gone)
The thing I like most about ruby is that the language gives you the tools to get the most out of your code so you don’t end up inventing classes, attributes or whatever just to make something as simple as supplying many values to a test.
Here’s a better way to do it in ruby:
[[1, 1], [4, 2], [9, 3]].each do |values|
test "sqrt #{values[0]}"
assert_equal values[1], sqrt(values[0])
end
end
Very good!
What makes this possible?
- Ruby lets you define code that will be executed at the class definition level
- Ruby lets you define methods dynamically (here the test function defines a “test_…” method)
Those two particularities makes the language really nice to work with.
Oh, but wait, there’s one more thing. I just found out I can do |input, output| in that last piece of code. It seems that if you iterate an array of arrays, you can specify many arguments to the given block and the i-th argument will match the i-th element of the array, so you don’t end up doing values[0] and values[1], which obfuscates the meaning of our code. Thanks again, ruby!
So, here’s the final code:
[[1, 1], [4, 2], [9, 3]].each do |input, output|
test "sqrt #{input}"
assert_equal output, sqrt(input)
end
end
String concatenation in ruby
I just found out the difference between += and << when used for a string.
irb(main):001:0> str = 'chan' => "chan" irb(main):002:0> str.object_id => 69952758899780 irb(main):003:0> str += 'ged' => "changed" irb(main):004:0> str.object_id => 69952758848800 irb(main):005:0> str << ', now not' => "changed, now not" irb(main):006:0> str.object_id => 69952758848800
So I think that basically you should never use += for strings, unless you really want to hurt the garbage collector.
Ruby-Jump plugin for gedit
I searched the internet for a gedit plugin that would allow me to press a key and jump (navigate) to the file where a ruby class is defined. I couldn’t find one so I wrote one (I know about Geany but I couldn’t find that functionality there either).
Usage
If the file you are editing is located in a ruby on rails projects, this will work automatically. If not, you will need to have the FileBrowser plugin installed and activated. The file browser should be pointing to your project’s root path.
Pressing F3 will jump to the file of the name under the cursor. This uses ruby convention so if your cursor is over the word SomeClass the file some_class.rb will be opened. It also works for some plural forms, so pressing F3 over :my_messages will try to open my_message.rb.
Pressing F4 goes to the test file of the name under the cursor, or to the test file of the current document if no match was found for the previous search. So pressing F4 over SomeClass will open some_class_test.rb.
Download
ruby-jump_0.2.tar.gz – Extract the contents of the file in /home/youruser/.gnome2/gedit/plugins
Keep an eye open on what LINQ does
Today I was profiling an application. The timings pointed to a piece of code that executed a query using LINQ. I opened an SQL profiler and saw what queries were performed. Here they are:
SELECT [t3].[value] AS [Key] FROM ( SELECT ( SELECT [t2].[Role] FROM ( SELECT TOP (1) [t1].[Role] FROM [dbo].[Membership] AS [t1] WHERE ([t1].[UserID] = @p0) AND ([t1].[SocialID] = [t0].[Id]) ) AS [t2] ) AS [value], [t0].[Id], [t0].[IsPrivate] FROM [dbo].[Social] AS [t0] ) AS [t3] WHERE (EXISTS( SELECT NULL AS [EMPTY] FROM [dbo].[Membership] AS [t4] WHERE ([t4].[UserID] = @p1) AND ([t4].[SocialID] = [t3].[Id]) )) AND ((NOT ([t3].[IsPrivate] = 1)) OR (EXISTS( SELECT NULL AS [EMPTY] FROM [dbo].[Membership] AS [t5] WHERE ([t5].[UserID] = @p2) AND ([t5].[SocialID] = [t3].[Id]) ))) GROUP BY [t3].[value]
SELECT [t0].[Id], [t0].[SocialName], [t0].[Title], [t0].[Description], [t0].[IsPrivate], [t0].[CreationDate], [t0].[LastModified], [t0].[Logo], [t0].[LogoUrl], [t0].[CustomSidebar], [t0].[AuthenticatedUserRole], [t0].[Activity] FROM [dbo].[Social] AS [t0] WHERE (((@x1 IS NULL) AND ((( SELECT [t2].[Role] FROM ( SELECT TOP (1) [t1].[Role] FROM [dbo].[Membership] AS [t1] WHERE ([t1].[UserID] = @p0) AND ([t1].[SocialID] = [t0].[Id]) ) AS [t2] )) IS NULL)) OR ((@x1 IS NOT NULL) AND ((( SELECT [t4].[Role] FROM ( SELECT TOP (1) [t3].[Role] FROM [dbo].[Membership] AS [t3] WHERE ([t3].[UserID] = @p0) AND ([t3].[SocialID] = [t0].[Id]) ) AS [t4] )) IS NOT NULL) AND (@x1 = (( SELECT [t6].[Role] FROM ( SELECT TOP (1) [t5].[Role] FROM [dbo].[Membership] AS [t5] WHERE ([t5].[UserID] = @p0) AND ([t5].[SocialID] = [t0].[Id]) ) AS [t6] ))))) AND (EXISTS( SELECT NULL AS [EMPTY] FROM [dbo].[Membership] AS [t7] WHERE ([t7].[UserID] = @p1) AND ([t7].[SocialID] = [t0].[Id]) )) AND ((NOT ([t0].[IsPrivate] = 1)) OR (EXISTS( SELECT NULL AS [EMPTY] FROM [dbo].[Membership] AS [t8] WHERE ([t8].[UserID] = @p2) AND ([t8].[SocialID] = [t0].[Id]) ))) ORDER BY [t0].[Title]
It doesn’t matter what the LINQ code that generated that query was. It looked “nice”. What matters is that I was able to change that LINQ code to do the same thing but using a different expression (instead of using EntitySets in the query, I used context.GetTable<…> and made the joins myself). Here’s the resulting query:
SELECT [t0].[Id], [t0].[SocialName], [t0].[Title], [t0].[Description], [t0].[IsPrivate], [t0].[CreationDate], [t0].[LastModified], [t0].[Logo], [t0].[LogoUrl], [t0].[CustomSidebar], [t0].[AuthenticatedUserRole], [t0].[Activity], [t1].[Role] FROM [dbo].[Social] AS [t0], [dbo].[Membership] AS [t1] WHERE ([t0].[Id] = [t1].[SocialID]) AND ([t1].[UserID] = @p0)
The timings were lower than with the previous queries.
So my recomendation is that you keep an eye open (preferably an SQL profiler open) to see how LINQ translates are queries.
Indentation also means something else…
Some days ago I read this in the Digital Mars D programming language newsgroup.
bearophile says:
http://jeremymanson.blogspot.com/2009/02/small-language-changes-for-jdk7.html
Automated Resource Blocks, to be able to say things like:
try (BufferedReader br = new BufferedReader(new FileReader(path)) {
return br.readLine();
}
instead of:
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
br.close();
}
and Andrei Alexandrescu (one of the designers behind the language) replies:
And he’s so right!
In D you’d write it like this:
Disposable disp = new Disposable();
scope(exit) disp.dispose(); // you can use braces too: scope(exit) { }
disp.doSomething();
disp.doSomethingElse();
I think this concept is really important. You want the important logic of your method to be always at the same indentation level. The things that, well, you need to do to cleanup things, catch errors, etc., should be on a separate indentation level so that the reader of the code (and that can be you, later!) understands it better.
That’s why I prefer this:
void process(Foo someObject) {
if (isNotValidForThisFunctionBecauseOfBar(someObject))
return;
if (isNotValidForThisFunctionBecauseOfBaz(someObject))
return;
// do something else with someObject
}
instead of this:
void process(Foo someObject) {
if (isValidForThisFunctionBecauseOfBar(someObject)) {
if (isValidForThisFunctionBecauseOfBaz(someObject)) {
// do something with someObject
}
}
}
Those last indentation levels are distracting. They are forcing you to read on cascade. The first example clearly marks which are the invalid values for the function, or the exceptional values to be handled, while the second one mixes those conditions with the main logic.
Constant Silverlight CPU usage? Double check your animations.
I had to fix a problem in a Silverlight application we are building. The problem was that it’s CPU usage was constant, between %20 and %40, and never stopped. I won’t go into the details of how I discovered the problem, but I’ll tell you what the problem was, and how we solved it.
The application
In our application we have dynamic content that is requested asynchronously to a web service. While the request is made, we show a small spinning donut. When the request is done, we remove the spinning donut and replace it with the content we want to show. The spinning donut is a tiny xaml with an animation that loops forever.
The problem
When the donut is removed from the page, the animation keeps looping until the garbage collector reclaims it, and that might take a long time. So the CPU usage was wasted due to that invisible animation which was no longer used.
The solution
Before replacing the spinning donut, we stop the animation. That solved the problem.
Unfortunately, Silverlight controls doesn’t implement IDisposable, so you can’t just stop the animation in a Dispose method. You have to do this manually.
I hope Silverlight makes each DependencyObject or UIElement implement IDisposable in the near future.
Why Java generics don’t have problems with right shift operator?
You know that in C++ a template instatiation like:
Foo<Bar<Baz>>
Type:
Identifier [TypeArguments]{ . Identifier [TypeArguments]} {[]}
BasicType
TypeArguments:
< TypeArgument {, TypeArgument} >
TypeArgument:
Type
? [( extends |super ) Type]
Foo<Bar<Baz>>
// when consuming a rule...
case 538:
if (DEBUG) {
System.out.println(
"ReferenceType2 ::= ReferenceType RIGHT_SHIFT");
}
consumeReferenceType2();
break;
case 544:
if (DEBUG) {
System.out.println(
"ReferenceType3 ::= ReferenceType UNSIGNED_RIGHT_SHIFT");
}
consumeReferenceType3();
break;
Autocomplete in Silverlight
I’ve written a simple class to allow adding autocomplete to a TextBox. An example of how to use it is:
In the XAML file:
<TextBox x:Name="uiText" Width="100" Height="30"
manas:Autocomplete.Suggest="DoSuggest" />
In the class file:
// The texts we want to suggest
private string[] options = new string[]
{
"Al", "Amiko", "Angla", "Anglujo", "Ankaux", "Antaux", "Atomo", "Auxto",
"Bebo", "Bela", "Birdo",
}
// The method we have to implement to offer suggestions
public void DoSuggest(string text, SuggestCallback callback)
{
// Don't suggest if there's no text
if (text.Length == 0)
{
callback(null);
return;
}
var result = new List();
// See which options have as a prefix the text entered by the user
foreach (var option in options)
{
if (option.StartsWith(text, StringComparison.InvariantCultureIgnoreCase))
{
result.Add(new Suggestion() { DisplayString = option,
ReplaceString = option });
}
}
callback(result.ToArray());
}
As in a previous post, I use the technique to specify an action to happen in the XAML, and it’s implementation in the class file, just like an event handler.
Of course, instead of using an hardcoded options array, these could be requested in the DoSuggest method to a web service, or requested from another class.
The suggestions are shown in an unstyled ListBox, but it should be easy to style, and even to improve the code to support icons in the suggestions, or any other control.
For this to work, the RootVisual of your application must be a Canvas, since otherwise you can’t place arbitrary floating elements on top of it.
Here’s the full code in case someone finds it useful.
Embedding YouTube videos in Silverlight
There’s no straight way of embedding YouTube videos in Silverlight. What you can do, however, is to create a floating div over the Silverlight plugin, whose content will be the YouTube video control. For this purpose, I wrote a simple class to make it easier to do this.
The usage is simple:
// ZCcedd9EfHI is the id of the video to show
YouTubePlayer player = new YouTubePlayer("ZCcedd9EfHI")
{
Top = 100,
Left = 200,
Width = 400,
Height = 400
};
player.Embed();
// And, once you want to remove the video from the page...
player.Dispose();
That’s it. Of course, you’ll have to compute the Top, Left, Width and Height values if you want to center the video inside a particular Silverlight control. You can do this computation in the Loaded event of that control.
And the best thing is, you can save a reference to the YouTubePlayer instance and, in case the Silverlight plugin is resized or moved, changing the Top, Left, Width and Height properties will automatically execute javascript code to move/resize the player.
Here’s the full code in case someone finds it useful.