Hoy un amigo me ha preguntado cómo podía completar una definición de paso (step definition) ya existente con una finalización opcional. Aunque la solución es simple cuando se conoce, si buscas no es fácil encontrarla en la red.
La clave está en conocer que las expresiones regulares tienen un tipo de agrupación que agrupa sin capturar: son los llamados "grouping-only parentheses".
En la expresión regular de una step definition cualquier parte entre paréntesis pasa a ser un parámetro del método que define el paso. Usando los paréntesis grouping-only evitamos este comportamiento, y si al final de ellos colocamos una interrogación (?) indicando que dicha agrupación es opcional, que puede aparecer o no, lo tenemos casi todo para tener un parámetro opcional.
¿Qué nos falta? Pues nos falta simplemente tener capturas dentro de esa sólo-agrupación-opcional.
El ejemplo, que siempre ayuda. Tenemos la siguiente definición de paso:
Dado /^que creo un post cuyo título es (.+)$/ do |title|
[...]
end
Y queremos que, opcionalmente podamos indicar también los tags que asociamos al post, completando la frase con algo como "... tageado con 'cucumber optional parameters'".
Dado /^que creo un post cuyo título es (.+)(?: tageado con (.+))?$/ do |title, tags|
[...]
end
Si en la feature sólo indicamos el título del post la regexp macheará y tendremos un nulo en el parámetro tags.
Esta técnica es perfecta si los parámetros opcionales están al final de la frase. La cosa cambia si están al principio o entre medias, ya que esa situación tendremos que añadir lógica dentro del paso para descubrir qué parámetros son los que nos han llegado, si es que es posible averiguarlo.
Los grouping-only sirven también para hacer los pasos más abiertos, posibilitando expresarlos de distintas formas igualmente válidas. Si en el ejemplo anterior queremos aceptar también "artículo" además de "post" podríamos escribir la definición de esta forma:
Dado /^que creo un (?:artículo|post) cuyo título es (.+)(?: tageado con (.+))?$/ do |title, tags|
[...]
end
Desde hace mucho tiempo he querido escribir un post sobre dos features de las expresiones regulares que me permitieron disfrutar como un enano del desarrollo de MundoPepino. Una de ellas es esta que he contado.
La otra es el "negative lookahead". A ver si encuentro un caso de uso chulo para dedicarle post y termino de cumplir mi deseo.
