Friday, December 16, 2011

Avoiding Rails's 'validates_uniqueness_of' hits the Database

Disclaimer: I am now working with Rails 3.0.X, so this can be solved in newer branches (or not).

Sometimes something that starts as an stupid doubt takes you to useful improvements.

This morning, I was wondering if ActiveRecord is smart enough to avoid hitting the Database with an Update, when you save an unchanged object. My intuition said that none UPDATE should be done if nothing really has changed. So, doing a 'save' is always safe.

I fired up the console and activated the SQL log (as described here ). It turned out that ActiveRecord is smart enought to avoid issuing an SQL UPDATE if object is unchanged.

However I noticed a SELECT access while saving. Mmmm ....... from nowehere?

Well, it was certainly from somewhere:

 validates_uniqueness_of :username

This innocent line was fired on each validation, even if username didnt changed. The solition was really simple:

validates_uniqueness_of :username, :if => :username_changed?

The check is skipped when no really needed.
Profit!





Thursday, October 13, 2011

Concat in place for Javascript arrays

This one is like black magic.
Javascript Array's concat method creates a new array with the concatenation of 2 arrays. However doing so in place is what you need most of the time:

being:
var a = [1,2,3] , b = [4,5,6];

Push does not work, since it works with  individual elements
a.push(b);
>>> [1, 2, 3, [4, 5, 6]
a try with 'concat' wont work:
a.concat(b)
>>> [1, 2, 3, 4, 5, 6] //returns a new array, where (a is still [1,2,3] )

but the trick is doing:
a.push.apply(a,b);
>>> [1, 2, 3, 4, 5, 6] // where a is [1, 2, 3, 4, 5, 6]




(*)To understand how apply works: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/apply http://trephine.org/t/index.php?title=JavaScript_call_and_apply



Tuesday, September 27, 2011

Rails: The power of 'inverse_of'

There is a 'less known' feature of ActiveRecord associations that is very handy: the ability of marking an association as the mirror of another :inverse_of

The best is to rescue an example from the oficial documentation

class Dungeon < ActiveRecord::Base
  has_many :traps, :inverse_of => :dungeon
  has_one :evil_wizard, :inverse_of => :dungeon
end

class Trap < ActiveRecord::Base
  belongs_to :dungeon, :inverse_of => :traps
end

class EvilWizard < ActiveRecord::Base
  belongs_to :dungeon, :inverse_of => :evil_wizard
end
 
dungeon = Dungeon.first
wizard = dungeon.evil_wizard 



In a normal configuration, doing wizard.dungeon will hit the database and instantiate a new 'dungeon' (2 instances of the same object). 
 
With :inverse_of , Active record is aware of the relation and will use the same instance in memory. This has 2 benefits:
- we save a DB call
- as both 'dungeons' are the same instance, modifications on dungeon are seen from wizard (an the otehr way around)
 
Without :inverse_of , a modification on dungeon, is not seen by wizard.dungeon what can lead to subtle errors.
 
+1 for :inverse_of 
 
 

Saturday, September 10, 2011

Capistrano, Database.yml and how to deploy without exposing your database passwords

The other day we wanted to secure our database, changing the user (instead of root) and password that Rails uses. Having them harcoded in database.yml makes it unsafe.

Fortunately we deploy through Capistrano, and there is a recipe for deploying using database credentials previously stored in the target machine. This way, database.yml is not available from source code and credentials remain private.

Everything is available as a gist here ( http://www.simonecarletti.com/blog/2009/06/capistrano-and-database-yml/ ) but I want to complete the information to save you some time.

The recipe is split into 2 tasks:
- generating the database.yml in the target machine (that will end with a cap deploy:setup )
- deploying , but using the database.yml in the target machine (that will end with the usual cap deploy)

Steps:
  1. Download the gist AND save it in /config/capistrano_database_yml.rb
  2. Follow Requirements point in the gist doc (or in the link above)
  3. Follow Usage point in the gist doc (or in the link above)
    1. Note that you must add a require line in your capistrano deploy.rb . This line should be: require "config/capistrano_database_yml" . Since it is searched in your $LOAD path
  4. Create a custom template as in the Custom template section of the gist doc.
    1. In our case we ask for user and password
    2. Save the template in config/deploy/database.yml.erb
    3. There is an error in the doc, at least for Rails 3. To make deploy prompt for user or password, use the usual arb syntax: <%= %> 
    4. We end with something like for the .erb:
      base: &base
        adapter: mysql2
        encoding: utf8
        pool: 5
        host: localhost
        timeout: 5000
        username: <%=Capistrano::CLI.ui.ask("Enter MySQL database username: ")%>
        password: <%=Capistrano::CLI.ui.ask("Enter MySQL database password: ")%>
      development:
        database: my_app_development
        <<: *base
      test:
        database: my_app_test
        <<: *base
      staging:
        database: my_app_staging
        <<: *base
      preproduction:
        database: my_app_preproduction
        <<: *base
      production:
        database: my_app_production
        <<: *base
  5. When the erb is saved. you can run the cap deploy:setup (or cap deploy:setup if you are in a multistage)
    1. this will create a database.yml in your_target_machine /shared/config/database.yml
    2. during this task you were asked for the username and password, and they will be written in the database.yml
    3. revise that the generated database.yml have the right privileges: will be accessible only to  the user you deploy and run teh application with
  6. Once done. You can deploy the application in the usual way. It will use the new database.yml
    1. cap deploy(or cap deploy)
For Jenkins, you must create (or copy) the database.yml to each of the jenkins 'projects'. As it runs test, you only need a database.yml with 'test' section. Revise the access rights of this file also (ex: chmod for Jenkins user only).
The location of databse.yml per project will be(in our case is):
/var/lib/jenkins/jobs//workspace/config/database.yml
 
Profit! 


P.S. As a bonus, take a look to this compilation of capistrano recipes:

https://github.com/webficient/capistrano-recipes


Rails: Log SQL queries to console

This is a quick tip.
Whenever you need to study sql accesses of your code, you can do it during a console session. Just need to configure the logger:

rails c
logger = Logger.new(STDOUT);ActiveRecord::Base.logger = logger;ActiveResource::Base.logger = logger;

 It will log every sql query to the console.

Thursday, September 1, 2011

Atina marido que la noche es corta

Ayer tuvimos un día duro intentando llevar una nueva feature a producción. Cómo siempre, en el último momento es cuando surgen los problemas.

En nuestro caso, tenemos la aplicación principal corriendo en un passenger+nginx, y un demonio que en background va completando tareas pesadas (hace pasadas cada 30s y 15m). El problema vino cuando nos dimos cuenta de que el servidor de preproducción estaba mandando mails cómo si fuera el de producción.

El primer pensamiento fue echar la culpa al demonio: es código hecho in-house. Pero estaba funcionando bien.
Lo siguiente fue revisar linea a linea los ficheros de configuración. Todo OK.
¿el capistrano? Todo correcto. Deployaba con el stage de preproduction.

Finalmente comprobamos que era la aplicación web principal la que estaba corriendo como si fuera producción. Glup!

La solución es tan tonta como modificar la configuración de nuestro nginx de preproduccion y añadir
rails_env preproduction;
bajo el apartado http (así afecta al servidor completo y evitamos futuros problemas). Reiniciar el nginx, y a disfrutar.

La explicación: passenger por defecto corre en el entorno production.









Sunday, May 15, 2011

The lines that save us days of work (Rails patch)

We do program Ruby On Rails over Windows OMG!.
Thanks to the RubyInstaller  project [*] the daily tasks run as smooth as if we were in a *nix based O.S.
There is however one thing that still make working over windows inferior than doing the same over linux: the full stack took longer to load. So, if you run tests too often you end up wasting a no little time at the end of the day.
There are a couple of things that you can do to cut the load time:
  1. Latests versions of Ruby (Ruby Gems) load faster than old ones.
  2. If you run an antivirus, exclude Ruby directory from analysis
  3. The king: http://gaertig.pl/blog/en/2010/06/how-to-speed-up-rails3-startup-on-windows-by-30-percent.html
It seems that the problem is in the Kernel::require method, that is unoptimized in windows. Fortunately you can patch it to increase the speed. Or more accurately, skip duplicated require invokations. Just add these lines at the beginning of your config/environment.rb .

unless ENV['RAILS_ENV'] == 'production'#Rails.env.production?
  #from http://gaertig.pl/blog/en/2010/06/how-to-speed-up-rails3-startup-on-windows-by-30-percent.html
  if not $SPEEDUP_LIBCACHE
    $SPEEDUP_LIBCACHE = {}
    module Kernel
      alias chained_require require
      def require(path)
        $SPEEDUP_LIBCACHE[path] ||= chained_require path
      end
      private :require
      private :chained_require
    end
  end
end


Thats all. BTW: I found no difference in linux: it already loads quickly.

[*] Remember installing DevKit ( https://github.com/oneclick/rubyinstaller/wiki/Development-Kit ) to automatically build gems with native extensions.

Monday, May 2, 2011

Para los que pasan muchas horas delante del ordenador: F.lux

F.lux es un sencillo programa que cambia el esquema de color de tu ordenador dependiendo de la hora del día. Llevo utilizándolo aproximadamente un mes y la verdad es que los ojos te lo agradecen.

Está disponible gratuitamente en http://stereopsis.com/flux/ para las 3 plataformas más extendidas (Win, Mac y Linux).
Software bueno, bonito, barato y UTIL.

Thursday, April 21, 2011

Add Rails Support to Netbeans 7.0

I always liked Netbeans for coding: it supports ton of languages, can be installed in Windows, Linux and MaC, and is stable in all of them. Even it demands more resources than a text editor, this is not a problem in current computers.

The latest release (7.0) dropped official support for Rails :( .
However you can continue using it via a community maintained plug-in:
  •  Install Netbeans from http://netbeans.org/downloads/index.html (I picked PHP distribution since it is the lighter one)
  • Add a plugin repository : 
    • Tools -> Plugins -> Settings 
    • click 'Add' and write a name (e.g: Beta rails) and a url 'http://updates.netbeans.org/netbeans/updates/7.0/uc/beta/stable/catalog.xml.gz'
  • refresh available plugins, filter by 'rails' and install it
  • Restart IDE, rescan Ruby platforms:
    • Tools -> Ruby Platforms --> Autodetect Platforms
 
Profit

 here are some links for more information on NB + Rails:
  • http://blog.enebo.com/
  • http://wiki.netbeans.org/RubyCommunityInformation 

Wednesday, April 13, 2011

Rendering from a Model in Rails 3

Call me 'rebel', but it happened to me that I had to render text from a ruby class.
I was composing text withing a regular class to send personalized SMS's and I wanted to use 'erb' templates and some other view utilities. Even it is not the Rails way, I wanted to do so.

Here are the tricks I used to build the logic. Key points are:
- how to get access to the view context
- how to get access to the path and the erb templates
- hot to get access to the url helpers in case you need form an url


class MyModel < ActiveRecord::Base
 
   # Use the my_models/_my_model.txt.erb view to render this object as a string
  def to_s
    url = helpers.new_user_url :host => default_host
    view = ActionView::Base.new(views_path)
    text = view.render(
      :partial => 'my_models/my_model', :format => :txt,
      :locals => { :my_model => self, :url => url}
    )
  end
 
  private
  def views_path
    @views_path ||= Rails.configuration.paths.app.views.first
  end

  def self.helpers
    @helpers ||= Rails.application.routes.url_helpers
  end

  def default_host
    #you need to configure it in your /config/environments/*.rb files
    # for example:   config.action_mailer.default_url_options = { :host => 'localhost:3000' }
    @default_host ||= Rails.configuration.action_mailer.default_url_options[:host]
  end
 
 
end

Thursday, March 31, 2011

How to uninstall all Ruby gems

If you ever need to uninstall all gems in your system, just use:

sudo gem uninstall --all --ignore-dependencies `sudo gem list --no-versions`
 
If you are in  widows, remove the 'sudo' part.

If you are using 'rvm' prepend rvm to the gem commands.

If you were using bundler, you only need to reinstall bundler gem, and run the bundler install, to have removed obsolete gems.

Sunday, March 13, 2011

Placeholder emulation via Javascript

Recently I was asked to include a placeholder functionality in a form ( http://diveintohtml5.org/forms.html )
Even I prefer labels for such a task, it seems that placeholders are cooler nowadays.

The problem started when I realized that only Safari 5 and Firefox 4 support them. Between all the crossbrowser fallback replacements that I checked, none of them seemed 100% of my liking:
So, instead of rushing into the keyboard  I thought it should not be so dirty.
Luckily I came across with Tumblr and how they solved the problem. The trick is very clever and i decide to experiment with something similar.

In the beginning you have the typical  label and the input. Both surrounded by a container, that we call wrapper. This wrapper can be a <li>, <p>, <div> or whatever.
 The trick consists of placing the label behind the input via CSS (this is the reason we need a wrapper) and using Javascript to change the appearance when we write some text.

There are 3 states we should control:
- Empty (quiet) state: There is no text in the input and the label text is shown
- Focused state: The input gained the focus and the label should fade to ease the user input
- Filled state: Some text has been written in the input. We show ONLY the input text but not the label

- Error state: for completeness we can add a fourth state. When the form has been submitted and the field contains errors, we show a descriptive message and change the appearance.



Javascript is used to detect changes and transition between them. The logic is simple: it checks for focus / blur events, and if the input is empty or not. All the appearance is controlled via CSS, and javascript only has to add and remove CSS classes.

About the CSS styling there are a couple of comments:
- absolute positioning is used to place label and input in the same place.
- z-indexes are used to place the label behind the input. Note that input cannot have a totally opaque background or the label will be hidden. You can use a transparent background picture, a gradient or just declare it as transparent.
- Depending on your styles, you can spend a little time aligning the label and the input.

 One good thing of this solution is that it can be easily tunned to cope with scenarios where javascript is not enabled. Instead of having the 'wrapper' class assigned, you can add it via javascript. If it is not added, you have the usual label + input combo.

The javascript I am using is something like:

(function PlaceholderLike($,window){

    var Placeholder = function(container){
        this.container = $(container);
        this.empty = true;
        this.bind_events();
    }
    Placeholder.prototype = {
        bind_events : function(){
            var placeholder = this, check_input = function(){
                if(this.value){//'this' is the input
                     placeholder.empty && placeholder.container.addClass('filled');

                }else{
                    !placeholder.empty && placeholder.container.removeClass('filled');
                }
                placeholder.empty = !this.value;
            }
            placeholder.container.find('input').bind('focus.placeholder_like',function(){
                placeholder.container.addClass('focused');
            }).bind('blur.placeholder_like',function(){
                placeholder.container.removeClass('focused');
            }).bind('change.placeholder_like',check_input).bind('keydown.placeholder_like',function(){
                var self = this,
 // the hot values are when we are around 0 (+1 or -1 char)
                should_check = (this.value || this.value.length <= 1); 
                should_check && setTimeout(function(){
                    check_input.call(self);
                },1);
            }).triggerHandler('change.placeholder_like');
        }
    }

    $.fn.placeholder_like = function(options){
        this.each(function(){
            new Placeholder(this);
        })
        return this;
    }
})(jQuery,this);

//and it is used with a simple call 
$('.input-wrapper').placeholder_like();

P.S: While I was writting this, i discover that I was not the only that think on something similar: http://fuelyourcoding.com/scripts/infield/