Fine grain control on Sinatra Routes

At times, you might require fine grain control on the your Sinatra routes.
For example, for the controller path /users/<user_id> , the following would be valid calls –
/users/123 or /users/abc or /users/d6e881d33949470f9df4aa39606d03ea

Now, if you have the user_id as a uuid, you have to validate the user_id every time. Instead of validating the uuid yourself, you could ask Sinatra to reject the request if the provided user_id does not match the uuid pattern.
So, assuming your user_id to be UUID (length 32), instead of defining your controllers as –
put :create, map: ‘/users/:user_id’
you can define them as follows –
put :create, map: %r{/users/(?<user_id>[a-z0-9]{32})}

Notice the <user_id> in the above regular expression. This is match group in a regex and you can get the user_id using the regular params object –
user_id = params[:user_id]

Details here – Sinatra Routes


Home Printer buying – why it is better to NOT buy a Canon Printer!

I bought a Canon Printer (Print, Copy, Scan – INR 3500) some 3 years back from Nehru Place. The guys there advised me not to buy it because of no resale value. They suggested to buy the HP one instead. But they were a bit late as I had already purchased one. And well, impressed with what I had bought, I ignored their comments. Who wants to sell a printer anyways! And if I decide to sell, what price would I get from the INR 3500 printer.

Looking back now, I feel that they were right not only because of the resale point but also the following points –
1. The running cost is exorbitantly high for Canon printers. This is simply because the Cartridge cost is very high.
2. The availability of Cartridges. It is difficult to get Canon cartridges from local shops. So, my dad who is the primary user of the printer had to either go to Nehru Place to buy them or I had to order them through Flipkart.

Now, both the inks are empty and hence no printouts. I am given the task of fixing the printer. The only point I am deliberating now is whether to invest in Canon cartridges or buy a new printer itself. I zeroed-in on an HP wireless printer for the comfort of printing wirelessly (~INR 6000) but still have to make the decision of buying the Canon cartridges vs the new HP printer.

Here is a quick comparison –
Approximate prints requirement per year

Mono Color
800 150

Per page cost

Cartridge Type Cost Yield (pages) Cost/page
Canon PG 810XL Black 1260 401 3.14
Canon CL 811 Tri-color 1335 244 5.47
HP 678 Black 500 480 1.04
HP 678 Tri-color 500 150 3.33

Running cost per year – Existing printer (Canon)

Cartridge type Pages to print Total Cartridge Cost per Cartridge Total Cost
Black 800 2 1260 2520
Color 150 1 1335 1335
Total/Year 3855

Total Running cost for two years = 2 x 3855 = INR 7710

Running cost per year – New Printer (HP)
First Year: New Printer Cost – INR 6000 with 1 black and 1 color cartridge.
Additional Cartridges –

Cartridge type Pages to print left Total Cartridges Cost per Cartridge Total Cost
Black ~400 1 500 500
Total 6500

 Second Year

Cartridge type Pages to print Total Cartridges Cost per Cartridge Total Cost
Black 800 2 500 1000
Color 150 1 500 500
Total 1500

Total Running cost for two years = 6500 + 1500 = INR 8000

As you see here that the cost is almost same after two years and you get –
1. The benefits and Warranty of latest new printer
2. Convenience of a wireless printer
3. Low running cost
4. Convenience of ordering the Cartridges online through HP directly. HP provides this facility. So, no more searching around Canon Cartridges.

Note: This is just an approximate calculation. After I did this calculation, I checked with my dad and he says that currently he buys more than 3 black and 1 color Canon Cartridges per year. That’s more savings if I move to the HP Printer.
Sources: Prices: Flipkart, Yield: the respective websites of Canon and HP

PUT vs POST while creating a resource

The most asked question and one where I have seen the most inconsistency and interchangeable use in REST APIs is whether to use the HTTP method PUT or POST while designing a REST API to create a User entity.
Usually, I have seen suggestions such as use POST to create and PUT to update, or use POST to create and update.
Though, it depends on how you want to model your APIs and many more factors, the most simplest approach that can get you started and help you to distinguish and decide which HTTP method to use is to know whether –
The Entity’s id is provided by the client, with the API path similar to – /v1/users/{user_id}
The Entity’s id is created on the server, with the API path similar to – /v1/users

If the id is provided by client, you can go for PUT, that is, PUT /v1/users/{user_id}
Else, go for POST, that is POST /v1/users

Note: For a more detailed explanation, refer to this stackoverflow thread

Coding productivity in Flash Builder 4.5

I know I’m a little late in posting this but it’s better late than never!! 🙂
So, with Flash Builder 4.5 we introduced a lot of new coding productivity features. Know about the new features here

What more… The Quick Assist feature is extensible. It means that you can write your own quick assists and use them or share them within your team. Sreeni has posted a nice write-up on how to extend quick assists. See more details here

Enjoy Coding!!!

GroupingCollection with improved performance

There were some concerns over the performance of GroupingCollection class while grouping and calculating summaries.

So, a new class GroupingCollection2 is introduced in the data visualization components.

The major improvements in GroupingCollection2 are –
1. Grouping performance improved.
2. Summary calculation performance improved. Now, instead of looping over the data again and again, summaries are calculated in a single loop.
3. When using async refresh, the summaries are calculated as soon as each Group is built. Earlier, the summaries were calculated only after all the Groups have been made.

What has changed –
1. Introduced class GroupingCollection2 which replaces existing class GroupingCollection.
2. Introduced class SummaryField2 which replaces existing class SummaryField.

No no, classes GroupingCollection and SummaryField are not removed.
They will continue to exist to maintain backward compatibility.
So, you can use either GroupingCollection or GroupingCollection2 and AdvancedDataGrid will continue to work 🙂

The difference between SummaryField and SummaryField2 is –
SummaryField2 does not have “operation” and “summaryFunction” properties.
A new property “summaryOperation” in added in SummaryField2. It is an Object which takes one of the following –
* SUM, MIN, MAX, AVG or COUNT as String.
* An implemtatation of mx.collections.ISummaryCalculator for calculating custom summaries.
The default value is SUM.

API changes –
1. Method refresh() has been changed in GroupingCollection2. The syntax now is –

function refresh(async:Boolean = false, 
		dispatchCollectionEvents:Boolean = false):Boolean;

Code changes required to start using GroupingCollection2 –
1. Use GroupingCollection2 instead of GroupingCollection.
2. Use SummaryField2 instead of SummaryField.
3. Replace operation/summaryFunction in SummaryField with summaryOperation in SummaryField2.

An example is shown here:
With GroupingCollection –

<mx:GroupingCollection id="gc" source="{arr}">
		<mx:GroupingField name="name" >
				<mx:SummaryField dataField="sal" 
					operation="MAX" />

With GroupingCollection2 –

<mx:GroupingCollection2 id="gc" source="{arr}">
		<mx:GroupingField name="name">
			<mx:SummaryRow >
				<mx:SummaryField2 dataField="sal" 
					summaryOperation="MAX" />

Try it and let us know your feedback.

serializationFilter in HTTPMultiService

HTTPService/HTTPMultiService have a cool concept of a Serialization Filter. This mechanism let’s you configure and manipulate various aspects of the HTTP call like the request, response, etc..
A default implementation of SerializationFilter is provided in mx.rpc.http.SerializationFilter

Usage –
You can create a custom SerializationFilter by extending from the default implementation and set it on the HTTPService instance or the Operation instance.

A sample implementation can be as simple as processing the response from the service.
For example, if your service returns a comma (,) separated list of values, you can convert it to an Array here.

import mx.rpc.http.AbstractOperation;
import mx.rpc.http.SerializationFilter;

public class CustomSerializationFilter extends SerializationFilter
	override public function deserializeResult
		(operation:AbstractOperation, result:Object):Object
		var arr:Array = [];
		if (result is String)
			arr = String(result).split(',');
		return arr;

And no, this is not all, there are other methods also which exposes more functionality.

For example, you can use the serializeURL() method to process/modify the url which this service/operation is about to invoke.

Livedocs here