redilious/blog

Saturday, May 25, 2013

Why?

TL;DR: Rails is a great tool to set up a development environment for single-page apps, particularly if you already know the framework. Skip to How to get started.

When writing single-page apps using frameworks like Backbone.js or Ember.js, I found myself frustrated by the lack of development environment, coming from the Rails world where a lot of tools are provided to keep your code clean, organised and optimised.

I tried tools like rake-pipeline and Yeoman, but ultimately I was disappointed, craving a tool that would do just like Rails with its assets pipeline, but without the actual Rails stuff. Until a few days ago, my friend and colleague Kevin interrupted my rant: "Why not Rails"?

Here is what Rails can do for you, and I will show you how:

Splitting code into multiple file (readability): There is one eyesore I find common to all demos and tutorials of JavaScript frameworks: app.js. Somehow, learning to build a single-page app always seem to include cramming all of your code into one huge, disorganised, unmaintainable and overall disgusting JS file.You can't reasonably work like that, at least not for long. I want each model, each view, etc in a separate file.

Using SASS and CoffeeScript: Hardcore JS developers might argue against CoffeeScript, but I can't possibly go back. And I don't think anyone can argue against SASS. It's just awesome.

Joining and compressing JS/CSS (performance): If you split your JS and CSS files and then include them all in your app, you need to stop. Each additional link or script means an additional requests, which means more delay before rendering your app. And obviously, your assets need to be minified before hitting production.

Updating librairies (maintainability): All the common librairies and frameworks such as Backbone.js, jQuery, Bootstrap and Foundation are available as Ruby gems, which makes installing and updating them a lot easier than browsing all the websites regularly and downloading the new versions.

Watching for changes: In development mode, Rails will recompile your assets automatically if you change them, so you can skip between your code and your browser without stopping by the console first.

But isn't it overkill to use a complete web framework just to manage your assets? Maybe a little, but who cares? It's not like your Rails app is ever going to production, so nothing changes on that front, and Rails is as easy to install as the other tools you might find like Yeoman or Compass.

How?

I will assume you have Rails installed, and I will try to make this easy to follow for non-Rails developers, but you might want to read about the asset pipeline if that is the case.

At the time of writing, Rails 4 (RC1) still has some bugs affecting the assets pipeline, so I strongly recommend you stick to Rails 3. I tried to make this Rails 4 ready, but I might have forgotten some details. And besides, we won't use any of the cool new stuff from Rails, so there is zero advantage to living on the edge here.

First, let's create a new Rails app. We add flags to exclude stuff that we won't need, although it wouldn't hurt if it was there. Our built app will go in the public directory, so let's clean it out.

Next we open app/assets/javascripts/application.js, and remove what we don't need. Delete these lines:

We want the resulting files to be called application.js and application.css, but by default Rails adds a digest to that name. Change this line in config/environments/production.rb:

Finally, we can create our index.html. Place it in the public directory:

You can now work on your app like you would on a Rails app, except you will only modify the assets and not do anything in Ruby nor Rails! Start the server with rails server and open localhost:3000 to see that everything is working.

To build you app, just run rake assets:precompile. Everything will be built in the public folder. Remember to run rake assets:clean when you are done, or else Rails will continue to serve the files in public instead of your actual source files.

Tuesday, May 15, 2012

I was watching Yehuda Katz's latest talk at RailsConf 2012 (which is great by the way), and I realized he was using a native file browser in MacVim which looked pretty awesome (I don't really like NERDTree).

So I was pretty happy when my friend Yannick pointed me to the project, but I didn't want to compile it by hand. I've really gotten used to brew and, I'll admit, a little lazy. I like when stuff just updates itself, because I would never update it otherwise. Which is why I made the macvim-split-browser brew formula.

Open a terminal and run prepare_disk.sh from the kit by typing:cd Downloads/Lion_M860TU/sh prepare_usb.shReplace the directory by the one you extracted the kit to

Installing Lion

Backup all your dataI recommend using Time Machine so you can restore easily on your new Lion

Reboot, and make sure to boot on your USB drive (press F1 during boot to choose the startup disk).

Choose your USB drive from the menu (called Kakewalk).If you get a Kernel panic here (dark screen with reboot message), power off and start again but type "-x" before pressing enter to choose your disk.If you get stuck on the Apple logo and nothing else (no spinner, no disk activity) for a few minutes; just power off the computer and start again.

Saturday, July 9, 2011

After neglecting Minidoudou for a while, I am making it my priority project for now! There is still some work to do before it is ready for contributors, so here's a small list of the main changes I'm going to do:

Add user authentication with Devise (contributors only, you don't need to login to customize a ROM)

Add some info to the ROMs: uploader, link to original release, link to MDD release

Add Capistrano for easier deployment

Find contributors willing to upload ROMs and configure them

You can follow the progress on GitHub, and if you want to contribute to the source code (or by uploading a ROM), don't hesitate to comment/e-mail/tweet/poke.

Thursday, September 23, 2010

Cappuccino allows to forward unhandled messages to another object, similarly to Objective-C's forward and Rails' method_missing functionalities.
However, I couldn't find any documentation on this matter, which is why I found useful to detail it a bit here. As all this information comes from message boards and mailing lists, please forgive me if some details are missing or unclear, and feel free to comment if you have deeper insight on the subject.

What is invocation forwarding?

Invocation forwarding allows an object to forward unsupported invocations to another object. In simpler terms, let say you have an object with no methods, we'll call it empty_obj, but which has forwarding set to another object, working_obj (we'll see how in a minute). When you call [empty_obj doSomething], you won't get an error like you would expect, but instead the return value of [working_obj doSomething].
This might seem useless, but can actually prove quite necessary when you use wrapper classes for instance, that should forward most methods to another object.

Let's see some code!

Let's declare the SomeWrapper class, which does nothing but include a SomeClass object.

Except for its pretty standard init: method, this class does nothing. However, all method calls will be forwarded to o, so our wrapper will look like it implements all the methods from SomeClass.
You probably guessed that it's all thanks to the implementation of methodSignatureForSelector: and forwardInvocation:, so let's see what each does and how you can use them to match your needs.

- (CPMethodSignature)methodSignatureForSelector:(SEL)selector

This method is used to determine if a selector can be sent to an object. Here, we say YES no matter what, so we delay the error to the second invocation (in forwardInvocation:).
You could also check what the selector is, for example to hide certain features of SomeClass. Doing so is as simple as comparing two strings (hint: one of them is selector), and return YES or NO to accept or revoke the call, respectively.

- (void)forwardInvocation:(CPInvocation)anInvocation

As you probably know by now, this is where the magic occurs. The anInvocation parameter is the invocation that was sent to this object. Being itself an instance of the CPInvocation class, it can me manipulated in lots of ways.
Let's have a look at its three most interesting methods: invokeWithTarget:, setReturnValue:, and setSelector:. invokeWithTarget:, which is the method we used in our example, invokes the same selector, with the same arguments, on another target. This is the basic form of forwarding. setSelector: is pretty self-explanatory, it will change the selector used the next time you call invoke on the object (probably at the next line). This means you can accept a selector, but forward another, which offers endless possibilities. setReturnValue: will, well, change the return value. So now, you can have an class that returns a specific value, no matter the method invoked, simply by changing the invocation to [anInvocation setReturnValue:42] !

Using attributes instead of methods

As far as I know, you cannot use the forwarding mechanism with attributes. This seems to make sense, as attributes are a JavaScript feature where methods are an Objective-J enhancement.
However, what you can do is convert a method invocation to fetching an attribute. Here is how it should look like:

Instead of invoking our method on o, we retrieve the selector, use it as a parameter that o should have, and use the result as the return value.

No return!

You might find this CPInvocation handling is quite a hassle. In my setReturnValue: example, why didn't I simply use return 42 instead of calling a method on anInvocation.
Well, the answer is simple: forwardInvocation: has a return type of void, because anything you return will be lost. It is not called by Objective-J in lieu of the "real" method (the one you called but doesn't exist) the way you regularly call methods, and changing the return value won't help, either. No big deal, but pay attention to it.

However, the forward: method works in a way more similar to Objective-C, but you'll have to check the source code to see exactly how that works.

I hope you learned a powerful tool today, one that was cruelly missing from JavaScript.