quarta-feira, 10 de junho de 2015

Filme: As Vantagens de Ser Invisível

Achei um ótimo filme, depois de algum tempo descobri que existia o livro, comprei.

A adaptação para o cinema ficou muito boa, mas pra manter o chavão e ser sincero: o livro é melhor que o filme.

Repetindo, a adaptação ficou muito boa, mas um detalhe em específico me deixou muito chateado.

Em um determinado momento, Charlie (protagonista), vai defender seu amigo Patrick, que está apanhando de uns 5 caras.

No filme, parece que Charlie adquire uma força sobrenatural e nocauteia um dos brutamontes, mas no livro ele sabe bater, aprendeu com o irmão. Bata nos olhos, garganta e joelhos. Acho que isso é kung fu, não?

Um ótimo filme sobre a adolescência, seria ainda melhor sem essa apelação para o fantástico.

quarta-feira, 27 de maio de 2015

From Heroku to Dokku

I really like Heroku, it's very convenient!

Convenience normally have a price and this start to hit me. I was paying $20 for SSL endpoint and more $9 for database. Almost $30 for an application that is being reestructured and not accepting new clients, so no money!

After some googling I find this http://donpottinger.net/blog/2014/11/17/bye-bye-heroku-hello-dokku.html and decided to give it a try. I decide for the $5 plan in DigitalOcean.

I don't have any problem in deploying my application without configuring DNS, but after that I have to do so, because I use subdomains in my app. It's also good to have a hostname, because after installing Dokku you have to finish configuring it accessing the public IP address or your hostname if you already configured your DNS. As described in "Step 2: Setting up Dokku" of https://www.digitalocean.com/community/tutorials/how-to-use-the-digitalocean-dokku-application. Without this your app port will change in each deploy, so you can't have a stable URL for you app.

DigitalOcean already offer dokku 0.3.18, the latest version now, so you don't have to update it as Pottinger point out.

I have problem while compiling my assets, but after configuring DATABASE_URL to the database URL that I created there everything worked fine.

After everything configured, it's like pushing to Heroku, very cool!

Are you thinking in give DigitalOcean a try? Using the following link you win $10: https://www.digitalocean.com/?refcode=55506009d157

quinta-feira, 8 de janeiro de 2015

jQuery UI Draggable / Resizable with constrain and CSS scale transformation

There are a bunch of questions and solutions to the problems between the interaction of these technologies, these are the better solutions that I found:
  1. http://stackoverflow.com/questions/10212683/jquery-drag-resize-with-css-transform-scale
  2. https://gungfoo.wordpress.com/2013/02/15/jquery-ui-resizabledraggable-with-transform-scale-set/
  3. http://stackoverflow.com/questions/17098464/jquery-ui-draggable-css-transform-causes-jumping
Although they make an improvement, they aren't totally accurate. What they basically do is a calculation of the right position / size that the object must have after the interaction.

You can experiment with the example below, drag the small square to right. Your mouse will be outside the parent div before you hit the edge.

And now, the same example, with the solution presented in [3].

Nice, now the small square moves with the mouse, but it go beyond the parent when dragging or resizing and this was the tricky part to solve. I spend a day trying to figure out how I could solve this, so I'm sharing my solution.

First let's solve the draggable problem. The "bug" (jQuery UI guys don't want to address it, so it's not a bug) occurs because inside jQuery UI it's use absolute event positions.

Think about the parent without the scale, it will be bigger, right? So it's size to jQuery UI is beyond the limit of the scaled down version. What we need to do is inform jQuery UI that our representation is smaller.

I tried in many ways not monkey patch jQuery UI, but these efforts were fruitless. I had to expose the "contaiment" var in the ui parameter passed to callbacks. With this little modification I could use the start and stop callbacks to make jQuery UI work with my scaled containment sizes.

var dragFix, startFix, stopFix;

window.myApp = {
  layout: {
    zoomScale: 1
  draggable: {
    _uiHash: function() {
      return {
        helper: this.helper,
        position: this.position,
        originalPosition: this.originalPosition,
        offset: this.positionAbs,
        containment: this.containment

$.ui.draggable.prototype._uiHash = myApp.draggable._uiHash;

startFix = function(event, ui) {
  ui.containment[2] *= myApp.layout.zoomScale;
  return ui.containment[3] *= myApp.layout.zoomScale;

stopFix = function(event, ui) {
  ui.containment[2] /= myApp.layout.zoomScale;
  return ui.containment[3] /= myApp.layout.zoomScale;

dragFix = function(event, ui) {
  var deltaX, deltaY;
  deltaX = ui.position.left - ui.originalPosition.left;
  deltaY = ui.position.top - ui.originalPosition.top;
  ui.position.left = ui.originalPosition.left + deltaX / myApp.layout.zoomScale;
  return ui.position.top = ui.originalPosition.top + deltaY / myApp.layout.zoomScale;

Nice and clean, don't you think? After solving this, I guess that making resizable works would be easy. The inner workings of this can't be very different, right? Wrong, dead wrong. What I think will be solved in 5 minutes, take the hole day.

The resizable code is very different. I expected to see the same algorithms to apply movement constraints and other operations. This way, I had to find a new way to inform jQuery UI about my constraints.

After a day tinkering with resizable code trying to find a solution that need minimal changes to jQuery UI, like with the draggable code, I was unable to find a solution that I liked.

First, I realized that I need to change the methods e, w, n and s in _change to get correct widths and heights according to my zoom scale. This was something that could be done in the "resize" callback, but in this case it's too late in the algorithm, the scaled position is needed by internal methods, before we get a chance to change it.

After this I thought that I had ended, but resizing an element that isn't in the position 0, 0 make it grow beyond the edge of the parent. Digging a bit more, I found that I need some way to change the "woset" and "hoset" calculation, but I don't find anyway to do this without monkey patching the entire method.

The final solution is this:

Maybe you are asking yourself why I'm monkey patching. This is because I'm use Rails and I want to have the benefits of the asset pipeline.

I'm not very proud of it, so I would love to know better ways to accomplish my final result in a simple manner. If you know any, please share!

sábado, 3 de janeiro de 2015

New kid on the S3 direct upload block

Sometime ago I saw the post [Small Bites] Direct Upload para S3: a Solução Definitiva! do Akita. Ow, fantastic! I was just playing with S3 Direct Uploads solutions that are described around the web and that could save me lots of time and give me a well polished solution.

I start playing with refile and how I could integrate it with my application. It don't take much time to became disappointed.

I already use paperclip in my application, it's very well integrated, meets my requirements and I'd like how it organize files, so adapt what I have to refile would be a pain, but it opened my head that S3 Direct Upload can be simpler, so I decide to experiment.

I'd like how s3_direct_upload interact with S3, keeping the filename. This way I decide to make a hybrid of s3_direct_upload and refile: s3-upnow has born.

The idea of the gem is to be backend agnostic. For now it works only with paperclip, so if it's your upload gem, give a try to s3-upnow and your feedback. I guess that support others upload gems is not difficult.

I know that it's not well polished, but it's already working for me and maybe can work for you. If you find scenarios that it's causing problems, please let me know!

Happy hacking!

terça-feira, 30 de dezembro de 2014

Metaprogramming Ruby

I'm reading Metaprogramming Ruby 2: Program Like the Ruby Pros. I started to read it, because I guess that metaprogramming could make pieces of my code simpler, but I discovered that my problems are about abstractions. I just need better abstractions, nevertheless the concepts exposed in the book are very good and made me feel excited.

The first time I read about the Ruby object model I feel very impressed. Ruby is the first language that I learned with two concepts very new to me: dynamic typing and pure object oriented. So, understand how all the pieces fit together and get comfortable with the notion that everything is object, including classes, take some time to click.

I learn best by doing and now I'm experiencing an opportunity to apply metaprogramming (that I expect to blog in a near future). By doing and trying to understand what I was doing I can say that the Ruby object model clicked in my head, but one aspect that still confuses me a bit, and IMO isn't explained with great details in this book, is about method lookup.

How Ruby goes from the receiver of the calling to the location in the hierarchy of ancestors? One source of confusion was this picture:

I perceveid the object model in a very organized form: for each class, you have a singleton class and it's superclass is the singleton class of the class superclass. After you get it, it's not that complicated, but what I didn't perceived, was that in the middle of all this you can have modules!

This way, I was struggling in how I could add class methods to an existing class and also override some of it's methods. For example, for the following code:

module OneModule
  def my_method
    puts "OneModule.my_method"

class MyClass
  class << self
    include OneModule

How can I tweak my_method behavior? The first difficult that I had was map this code to the diagram above, since I didn't understand where the code was living.

After reading and re-reading the first chapters of Perrotta book, and tinkering with irb, I understand that it was going to the singleton class of MyClass.

This code provide insightful output:

p MyClass.ancestors
p MyClass.singleton_class.ancestors
p MyClass.methods(false) == MyClass.singleton_class.methods(false)
[MyClass, Object, Kernel, BasicObject]
[#, OneModule, #, #, Class, Module, Object, Kernel, BasicObject]

When you define a class method, it's stored in the singleton class. So if I would like to change a class method,  I have to change the singleton class, but this also puzzled me: how can I add it without removing the actual method?

From the output it's easy to see the solution, but it take me a while to realize that it was possible. I guess that the module methods where inserted in the singleton class, but the module is put as an ancestor of the singleton class.
With this knowledge in mind you can write the following:

module OtherModule
  def my_method
    puts "OtherModule.my_method"

class MyClass
  class << self
    include OtherModule

p MyClass.my_method
p MyClass.singleton_class.ancestors
[#, OtherModule, OneModule, #, #, Class, Module, Object, Kernel, BasicObject]

You can also call "super" in "OtherModule" and Ruby will chain the calls correctly.

After all, I still can't describe how method lookup works, and luckily someone blogged about it: Ruby's method lookup path, Part 1.

The algorithm can be resumed to the following:
  1. Methods defined in the object’s singleton class (i.e. the object itself)
  2. Modules mixed into the singleton class in reverse order of inclusion
  3. Methods defined by the object’s class
  4. Modules included into the object’s class in reverse order of inclusion
  5. Methods defined by the object’s superclass.
Armed with this, I'm by far better prepared to experiment and answer questions when they pop out. So nice, so good!

terça-feira, 16 de dezembro de 2014

Improved how to render coffeescript partial inside coffeescript template

Some time ago I googled trying to find a solution for render a coffeescript partial inside a coffeescript template in an attempt to DRY my coffeescript templates.

This led me to https://coderwall.com/p/i62phq/how-to-render-coffeescript-partial-inside-coffeescript-template. Initially I turn my nose for the syntax, but it solved my problem and wasn't that terrible so I stick with this.

After some time I need to debug my JS response and when I looked at the returned code I saw that I need a better solution:

(function() {
  (function() {
    $('.footer').html("<div class=\'btn-group\'>...<\/div>");

As you use more partials and your code start to grow this mess only gets worst. After hitting my head around a bit I realized that what I need was to render plain coffeescript, so I renamed my partial to _partial.coffee.erb and it worked like a charm!

Now my show.js.coffee is:

<%= render 'footer.coffee' %>

And my _footer.coffee.erb is:

$('.footer').html("<%= j render 'my_footer_html_partial' %>")

And the response is:

(function() {
  $('.footer').html("<div class=\'btn-group\'>...<\/div>");

Cleaner, don't you think?

segunda-feira, 8 de dezembro de 2014

Setup wildcard subdomain with Bind

I found a good documentation about configuring a DNS server to use wildcard domains for development: http://superrb.com/blog/2012/09/24/how-to-set-up-bind-on-ubuntu-for-a-wildcard-development-domain

All went well in my setup, I just have to adapt some paths and made use of bind conventions described in arch wiki.

All well, except the fundamental: wildcard subdomain. After googling a bit and read some similar questions in stackoverflow this was my final configuration:

  • /etc/named.conf
zone "dev.com" {
        type master;
        file "dev.com.zone";

  •  /var/named/dev.com.zone
; BIND data file for local loopback interface
$TTL 14400
@ IN  SOA dev.com. root.dev.com. (
            2014110801   ; Serial
                 86400   ; Refresh
                  7200   ; Retry
               3600000   ; Expire
                 86400 ) ; Negative Cache TTL
@ IN  NS  dev.com.
@ IN  A
* IN  CNAME dev.com.
@ IN  AAAA  ::1
If you don't catch the difference, I changed the line: "* IN A" with "* IN CNAME dev.com.".

PS.: This is NOT a tutorial, so read the post  linked in the start to make this works as you expect, since there contains what more you need to configure.