La Coctelera

por Guillermo Álvarez

image

nginx rails passenger mass deployment actually.

I typically deploys several applications that do not have much load on one machine. I use the advanced nginx virtual host technic(see Wildcard Subdomains in a Parent Folder).

I was rather surprised to see the article "new Passenger 3", especially in the aspect of mass deployment. Feature that since I have tested, works in nginx and Passenger series (do not know from which version).

The part of the nginx configuration that makes this possible is this:

 http {
     # [...]
     passenger_root /usr/local/lib/ruby/gems/1.8/gems/passenger-2.2.15;
     passenger_ruby /usr/local/bin/ruby;
         
     server {
         listen 0.0.0.0:80;
         root /var/www/servers/$host/public;
         access_log /var/log/nginx/servers.access.log;
         error_log /var/log/nginx/servers.error.log;
 
         location / {
            index index.html index.php;
            passenger_enabled on;
            autoindex  on;
         }
     }
     # [...]
 }
 
 

As soon as dir structure is as says on the documentation of Passenger (config.ru /tmp and /public) appears an application on the specific domain.


So if you want to deploy a new app, just put the files on the server.
ExtraBoll, for capistrano style deploys:
 http {   
     ...     
     server {
         ...
         root /var/www/servers/$host/current/public;
     }
 }
 

1, jul | sin comentarios Posteado por: cientifico compártelo Tags: ruby, rails, passenger, deploy, nginx, conf

El curioso bucle begin end while. Balbuceando en alto.

Creo que todos conocemos una sintaxis parecida:

  def function
    do something
    while condition 
      do something
    end
  end
En la mayoría de lenguajes tenemos que ejecutar el primer ciclo del loop fuera del loop.
Pero en Ruby no.
def temp_dir
  i = 0
  dir = File.join(Dir.tmpdir,'ginst', (i += 1).to_s)
  while(File.exists?(dir)) do
    dir = File.join(Dir.tmpdir,'ginst', (i += 1).to_s)
  end
  FileUtils.mkdir_p(dir)
end
Casi sin querer, descubrí la siguiente sintaxis
Esto hace que se ejecute el código la primera vez y luego...  si a la condición le apetece. Pero la primera, no te la quita nadie.
Esto me vino muy bien para hacer un generador de directorios temporales secuenciales:
def temp_dir(i=0)
  begin
    dir = File.join(Dir.tmpdir,'ginst', (i += 1).to_s)
  end while(File.exists?(dir))
  FileUtils.mkdir_p(dir)
end
Pero meditando un poco más, recordé una obviedad que tenía olvidada, y que la primera vez que la vi me sorprendió tanto como ahora, y es el poner el while a lo que quieras. Por ejemplo, si estás deprimido, qué mejor que estas cuatro palabras
puts 'Anímate' while true
Y si lo estás solo un poquito.
begin puts 'Venga tonto... ¡ Anímate ! ' end while false
Lo que me llevó a intentar hacer la función de los directorios en una linea
Primer intento:
def temp_dir(i=0)
  begin  dir = File.join(Dir.tmpdir,'ginst', (i += 1).to_s) end while (File.exists?(dir))
  FileUtils.mkdir_p(dir)
end
El problema que tenemos con esta sintaxis es que lo último en ejecutarse del bloque es la condición, por lo que no podremos obtener el valor devuelto. Ahora bien, si podemos pasar un begin..end...  ¿Quién nos prohibe pasar la sintaxis de toda la vida begin..begin..end..while..end .
def temp_dir(i=0)
  FileUtils.mkdir_p(begin begin dir = File.join(Dir.tmpdir,'ginst', (i += 1).to_s) end while File.exists?(dir) ; dir end)
end
De aquí, llama la atención el poder estar usando bloques dentro de argumentos con la misma facilidad que a mi se me convence para ir de fiesta.
Vale, hice una trampa. Inicializar la variable como parámetro. Pero tiene solución:
def temp_dir
  FileUtils.mkdir_p(begin begin dir = File.join(Dir.tmpdir,'ginst', (i ||=0 ; i+= 1).to_s) end while File.exists?(dir) ; dir end)
end
Pese a no ser práctico sobre ninguno de los casos expuestos, ya que ofuscar nuestro código, aunque mola, no es útil, me ha vuelto a llamar la atención, la versatilidad que puede haber en ruby.
Y como inquieto que soy... no puedo parar de preguntarme ¿y si...? Y sí funciona en ruby1.9, pero con la salvedad de que FileUtils.mkdir_p devuelve un array (creo que también los conocen como arreglos de algo) en vez de una cadena o string.
Y a tí... ¿ Hay alguna sintaxis de ruby que te llame especialmente la atención ?

21, abr | sin comentarios Posteado por: cientifico compártelo

Crear y eliminar tags remotos con git

Manejar tags localmente es fácil:

> git tag -l # lista los tags locales
> git tag tag_name # Crea un tag local
> git tag -d tag_name # Borra el tag local
>
> git tag -d `git tag -l ` # Borra todos los tags locales

Pero manejar los remotos... no es tan intuitivo, así que me dejo esta
pequeña nota:

> git fetch --tags #Aunque ya lo hace por defecto
> git ls-remote --tags origin # Lista los tags remotos

Y para borrarlo, tendremos que borrar primero el local y luego hacer:

> git push origin :refs/tags/tag_name

---Adjuntos---

smime-3.p7s

19, abr | sin comentarios Posteado por: cientifico compártelo

Variables especiales de ruby

A modo de chuletario personal, dejo esta imagen con las variables especiales de ruby.
Siempre conocida y sabida, hasta que requieres algunos de sus valores, es entonces cuando echas de menos este chuletario.

4, feb | 2 comentarios Posteado por: cientifico compártelo Tags: ruby, chuleta, variables, entorno, especiales, raras, jodidas de recordar, simbolos, raros, procees id, exit status, exceptions, line, number, regexp, match

Increible video.

31, ene | 2 comentarios Posteado por: cientifico compártelo Tags: video

Cucumber: Testeando ajax sin selenium (II)

Continuando con el artículo Testeando ajax sin selenium han mejorado algunas cosillas.

La versión anterio, tenía un problema y es que solo servía para visitar. ¿Pero que pasa con el resto de steps (como I press), que implican peticiones y que esperan ajax como respuesta? Pues aquí está la solución.

When /^(.*) as an ajax request/ do |task|
   When task
   response.body = get_ajax_html(response.body)
 end
 

Esto dota a las features de poder realizar cualquier acción que antes hacías y evaluar su respuesta. Por lo tanto, lo que antes era:

    And I press "Guardar"
 

Ahora es

    And I press "Guardar" as an ajax request
 

Como extensión, he visto que otras formas de page.update, usan la función javascript html en vez de replace with, por lo que la función que obtiene el cuerpo ha sido actualizada.

def get_replace_with_body(body)
   body=~/replaceWith\(\"(.*?)[^\\]\"\)/m
   body=~/\)\.html\(\"(.*?)[^\\]\"\)/m unless $1
   raise Exception.new('The ajax response doesn\'t containg a js replaceWith method') unless $1
   "#{$1}"
 end
 

Y ahora ya puedo testear casi todo el js sin usar selinium, configurar una máquina virtual, un xen, linux, firefox, selenium_server, etc...

23, ene | sin comentarios Posteado por: cientifico compártelo Tags: page update, muerte selenium, me voy, servidor, feature, ruby, page, update, js, ajax, webrat, rails, cucumber, infierno, satanas

Cucumber testeando ajax sin selenium

Como quería terminar una cosa, y lo que necesita más que test de vista o test de controlador era un test de integración, no me quedó otra que dotar a cucumber+webrat-selenium (nuestro entorno de feature testín) de capacidad de ajax.

Bueno, seamos serios, son un par de lineas que me permitieron hacer ejecutar la feature, y paso a comentar, ya que de tratarse de aplicaciones rails, este método es usable para la mayoría de page.update que realizamos.

page.update actualiza un elemento del dom con nuevo contenido, para eso lanza un javascript que es interpretado por el navegador. Suponiendo que usamos jquery (tal vez cambie la implementación para el antiguo y obsoleto prototype), este hará un replaceWith. Este código parsea el código devuelto por la aplicación y extrae la actualización de la página.

Pasemos ahora a ver el código:

# Desescapamos javascript, ya que escapado no nos sirve de mucho.
 # Así tendremos un html válido. Esto se resume en:
 #  < div id="\'hola\'">\tadios\t< /div>  ===>    adios  
 def unescape_javascript(javascript)
  javascript.gsub!('\n' , "\n")
  javascript.gsub!('\t' , "\t")
  javascript.gsub!("\\'", "'")
  javascript.gsub!('\"' , '"')
 end
 
 # Expresión regular encargada de sacar lo que realmente nos intersa.
 #  ...replaceWith(' ESTO NOS INTERESA ')...
 def get_replace_with_body(body)
  body=~/replaceWith\(\"(.*?)[^\\]\"\)/m
  raise Exception.new('The ajax response doesn\'t containg a js replaceWith method') unless $1
  "#{$1}"
 end
 
 # Combinado de las dos anteriores
 def get_ajax_html(text)
  unescape_javascript(get_replace_with_body(text))
 end
 

Y el step correspondiente.

When /^I visits by ajax (.*) $/ do |path|
  visits(path)
  response.body = get_ajax_html(response.body)
 end
 

Y la feature

 Scenario: Changing my name
    Given I am a logged in as a Candidate
    When I visits /profile/edit.js ajax
    And I fill in "candidate_profile_first_name" with "Guillermooo"
    And I fill in "candidate_profile_surnames" with "Alvarez"
    And I press "Guardar"
    Then I should see "Guillermooo Alvarez"
 

La solución es fea, torpe, poco optima. Pero creo que puede resolver la mayoría de peticiones ajax del servidor sin depender de un motor javascript externo.
Si alguien conoce alguna otra forma sin incorporar más dependencias al testing... que me lo haga saber.

23, ene | 1 comentario Posteado por: cientifico compártelo Tags: muerte selenium, page update, feature, servidor, ruby, page, update, js, ajax, webrat, rails, cucumber

Truquitos servidor

Basándonos en la teoría de que las máquinas están bien configuradas en lo que respecta el correo, yo voy a tener cientifico.net para correos personales y yolanda.cientifico.net para los correos locales de la máquina.

Esto permite que yo desde cualquier cuenta de correo envie un mensaje a guillermo @ yolanda cientifico PUNTO net.

Para que sirve esto.... pues para ser más comodón aún. Soy fiel usuario de scp (consola -> servidor) y webdav (escritorio<->servidor), pero poder enviar archivos a mi cuenta del servidor y al llegar allí, arrancar alpine o cualquier otro cliente de correo de consola, y poder guardarlo, es una gozada.

Ahí queda dicho.

5, ene | sin comentarios Posteado por: cientifico compártelo Tags: alpine, scp, servidor, escritorio, correo