¿Qué hace el guión el los Twig blocks?

Si abres el archivo

\vendor\symfony\symfony\src\Symfony\Bridge\Twig\Resources\views\Form\form_div_layout.html.twig

Verás que todos los blocks tienen este syntax: {%- …. -%}.

{# Widgets #}
{%- block form_widget -%}
{% if compound %}
 {{- block('form_widget_compound') -}}
 {% else %}
 {{- block('form_widget_simple') -}}
 {% endif %}
{%- endblock form_widget -%}

¿Qué significan los guiones? Es nada más que el whitespace control characterhttp://twig.sensiolabs.org/doc/templates.html#whitespace-control

Al principio pensaba que se trataba de un syntax especial para los bloques del core o algo asi … algo mágico y occulto … pero no. Al final una búsqueda me llevo a Stackoverflow: What does the hyphen mean for a block in Twig like in {% block body -%}?

CRM para mi – DWH CRM

Para entrenarme en Symfony2 y Doctrine, voy a hacer un CRM básico para ayudarme a controlar los contactos que hago mientras busco trabajo. Ahora tengo la información un varios archivos de texto, ordenados en carpetas, y, aparte de que necesito algo con que practicar el Symfony, veo que este método no servirá para muchos más contactos.

Objetivos

Con este labor quiero conseguir conocimientos de Symfony2 y principalmente Doctrine, y de paso un sistema útil de CRM para mis contactos. Además tendré otro GitHub repository de ejemplo.

Requisitos del CRM

Cada vez que veo un puesto o compañía y le mando un email o curriculum, quiero poder grabar los datos principales, e.g.

  • Empresa
  • Localidad
  • Persona de contacto
  • Descripción
  • Donde lo encontré
  • Fecha

Luego habrá una serie de eventos, e.g. ellos me contestan, yo a ellos, voy a una entrevista, etc. Necesito grabar ese información también:

  • Fecha
  • Descripción del evento

Entonces el sistema tiene que facilitar el acceso a esos datos con listas y búsquedas:

  • Lista de contactos
    • Lista de eventos por contacto
  • Búsqueda de contacto.

El repository vacío esta aquí: https://github.com/danksearle/DWH-CRM

 

Code Kata – Bowling Game

Bueno en el último post dije que iba a probar TDD, y ésto es el resultado del primer experimento. Leyendo el blog de Carlos Buenosvinos (lo recomiendo, esta lleno de cosas interesantes) encontré su post sobre el Kata “Bowling Game”.

Ya lo he hecho: https://github.com/danksearle/kata_bowlinggame.

2015-03-17_20-47-34

Ejemplos de los tests:

 public function testGivenGameExample()
 {
     $game = new Game;
     try {
         $this->processFrames($game, array(
             array(1, 4), // 5
             array(4, 5), // 14
             array(6, 4), // 29
             array(5, 5), // 49
             array(10), // 60
             array(0, 1), // 61
             array(7, 3), // 77
             array(6, 4), // 97
             array(10), // 117
             array(2, 8, 6), // 133
        ));
     }
     catch (Exception $e) {
         $this->fail('An unexpected exception has been raised. ' . $e->getMessage());
     }
     $this->assertEquals(133, $game->score()); // Test with rolls from the given example.

     return;
 }
 public function testPerfectGame()
 {
     $game = new Game;
     try {
         $this->processFrames($game, array(
             array(10),
             array(10),
             array(10),
             array(10),
             array(10),
             array(10),
             array(10),
             array(10),
             array(10),
             array(10, 10, 10),
          ));
     }
     catch (Exception $e) {
         $this->fail('An unexpected exception has been raised. ' . $e->getMessage());
     }
     $this->assertEquals(300, $game->score());

     return;
 }

Tardé un poco más que los 40 minutos de Carlos … un poco bastante. Bueno, hay que empezar de alguna forma. :-) Veo dos maneras de juzgar mis resultados. Primero “¿he hecho bien el Kata?” y segundo “¿he utilizado bien el TDD?”. Creo que me he pasado de largo los requisitos del Kata, o mal interpretarlos porque para entender las normas he recurrido a wikipedia … y creo que debería limitarme a lo que dice el kata y no buscar más allá. Pero era difícil entender cómo calcular los puntos en el último frame. Pero en la segunda cuestión creo que el TDD me ha ido bastante bien, no se si he escrito más tests de lo necesario, pero opino que menos tests no sería muy riguroso. Y al final tengo confianza en que calcularía bien cualquier partido.

Me esforcé a hacerlo siguiendo el principal de TDD de empezar con los tests, y luego el código.

Al principio era difícil de imaginar los tests. Empece con los fáciles, los tests de valid inputs, cómo string en vez de integer. Luego para probar con un partido entero añadí este method para facilitarlo:

 /**
 * Process an array of frames, each frame is an array of rolls.
 * @param Game $game 
 * @param array $frames
 */
 private function processFrames($game, $frames) {
     foreach($frames as $frame) {
         foreach($frame as $roll) {
             $game->roll($roll);
         }
     }
 }

Con éste función podría escribir los tests como en los ejemplos arriba, así son más legibles.

Entonces empece con los códigos, intentando solucionar los tests de uno en uno. A veces grupos de tests se solucionan con un solo cambio. Los últimos tests de caer eran los del method score(). Refactoré varios veces – la lógica me resultaba difícil de organizar. No se si era un requisito o no para validar los rolls en acuerdo con las reglas del juego, pero yo quiría hacerlo así. Entonces tenía código para validar, y luego código para calcular. Para validar mira atrás para ver en que estado esta el partido, pero para calcular el score por cada roll, si es strike o spare, mira hacía delante para buscar bonus points.

Es raro … al final cuando los tests eran todos verdes me di cuenta que tenía un class pero no tenía nada que lo utilizaba. “Normalmente” cuando haces un programa a terminarlo puedes ver lo en todo su esplendor, funcionando bien … pero yo solo tenia los resultados de los tests.

OK (25 tests, 7 assertions)

:) curioso. Hice un script pequeño basado en los tests para echo los resultados.

La duda sobre TDD que tengo ahora es como tener confianza en los tests … e.g. ¿mis tests realmente cubren todos los caminos del código? Supongo que combinas TDD con hacer tests con la aplicación final para comprobar que funciona bien. Pero en éste caso de la kata no puedo hacer esas pruebas y solo puedo leer mis tests.

Opiniones sobre “Is TDD dead?”

Ésto lo encuentro muy interesante.

http://carlosbuenosvinos.com/comentarios-al-hangout-is-tdd-dead/

Éste es el vídeo del Hangout al que Carlos y David están opinando:

Yo aún no he escrito un sólo test, estoy aprendiendo. He hecho muchos proyectos sin hacerlos, y tengo dudas sobre cómo funcionan y que beneficios aportarán, comparado con el coste de hacerlos. No quiero decir que opino que no son útiles, sólo que los desconozco. Toca meterme en el tema creo, manos a la obra pues … :)

Twig para romper lineas: escape, replace y raw

Estoy experimentando con el Twitter API y tengo unos tuits tirados en una página, aún falta poner algunos detalles:

2015-03-05_20-29-24

Al principio tenía este problema:

2015-03-05_20-28-44

Los URLs largos rompían su contenedor. Hay que poner unos <wbr> en ellos para romperlos en líneas. Para hacerlo cambié este trozo de un twig:

<p>{{ tweet.text }}</p>

para esto:

<p>{{ tweet.text|escape|replace({'+': '+<wbr>', '%': '<wbr>%', '%': '<wbr>%'})|raw }}</p>

Así rompemos justo después de los símbolos ‘+’ y justo antes que los ‘%’. Pero ojo a los filtros ‘escape’ y ‘raw’. Twig escapea los textos de forma automática, pero queremos los <wbr> tal cual, sin escapear. Entonces utilizamos el filtro ‘raw’ al final para decirle al Twig que éste texto ya esta bien, y utilizamos el ‘escape’ antes que el replace para escapear el texto original.

Al final tenemos esto:

2015-03-05_20-29-01

Twitter API 1.1 … fácil, no?

Pensaba que para practicar un poco utilizaría el Twitter API y pondría una lista de tweets en una página. No puede ser muy complicado, no? Pues ….

  1. Crear la application de Twitter … hecho.
  2. Leer un poco y concluir que sólo necesito Application only access.
  3. O “SSL absolutely required”! Necesito Connecting to Twitter API using SSL

… total, es un poco complicado. Instalé Go para crear un archivo pem de root certificates … Go parece interesante pero tengo otras cosas que aprender ahora. Hice un buen intento de construirlo yo, pero tenía problemas con que el servicio no me podiá “authenticate” y luego iba bien pero no me daba ningún tweet. Intenté con file_get_contents and luego con cURL.

Entonces leí esto en https://dev.twitter.com/overview/api/ssl 

When communicating with Twitter, it’s always best to use well-tested and predefined libraries to communicate with the API.

Y encontré TwitterOAuth. No es un Bundle de Symfony2, pero se puede instalar con composer. Lo instalas y aparece un tu carpeta vendor. Para utilizarlo en un service hay que poner esto al comienzo del código:

use \Abraham\TwitterOAuth\TwitterOAuth;

y luego algo asi para coger unos tweets:

// pon lo que te interesa claro :)
$query_array = array(
    'q' => 'empleo barcelona php',
    'count' => 30
);

$twitter = new TwitterOAuth(
    $this->twitter_api_key,
    $this->twitter_api_secret,
    $this->twitter_access_token,
    $this->twitter_access_token_secret
);

return($twitter->get("search/tweets", $query_array));

Y ahora tengo unos cuanto tweets con que jugar.

 

 

Symfony y Foundation

Al parecer muchos programadores en Barcelona utilizan Symfony y Foundation. Yo vengo de CodeIgniter, WordPress y Bootstrap, o más bien HTML casero. Para aprender Symfony y Foundation he empezado a rehacer mi sitio web (ya tocaba…). De momento va bien, ya superada la primera fase de instalar Composer y entender un poco como esta organizado.

Hice una lista corta de los comandos más útiles, para copiar y pegar:

php symfony.phar new myproject
php app/console assets:install web
php app/console cache:clear --env=prod
php app/console assetic:dump --env=prod --no-debug