Ruby: El operador ‘~>’ y el Gem::Requirement
En un hilo de ror-es con tÃtulo: ‘Problema con carga de rubygem en App rails al hacer rake db:create && rake db:migrate‘, Andrés Gutierrez se debatÃa con las versiones de las gemas solicitadas por un proyecto Rails que esta intentando arrancar.
La configuración del proyecto le requerÃa tener instalada una gema y para indicarle la versión se utilizaba el operador ‘~>‘.. no el ‘==’, el ‘>’, el ‘>=’.. no, tenÃa el simbolito raro ese de la ñ.
En concreto la especificación de la gema requerida es tal que asÃ:
config.gem 'mislav-will_paginate', :version => '~> 2.2.3', :lib => 'will_paginate', :source => 'http://gems.github.com'
Su duda venÃa de que él tenÃa instalada la versión 2.3.6 de la gema en concreto y no entendÃa porque no cumplÃa los requisitos.
El caso es que me piqué y al más puro ‘estilo Daniel R. Troitiño‘ ahà que fui a las tripas del código a ver que demonios hacÃa el operador ése..
Si miramos el fichero:
$ mate rubygems/requirement.rb
Tenemos la lista de operadores y lo que se hace con cada uno:
OPS = { "=" => lambda { |v, r| v == r }, "!=" => lambda { |v, r| v != r }, ">" => lambda { |v, r| v > r }, "<" => lambda { |v, r| v < r }, ">=" => lambda { |v, r| v >= r }, "<=" => lambda { |v, r| v <= r }, "~>" => lambda { |v, r| v >= r && v < r.bump } }
Donde ‘v‘ parece ser la versión disponible y ‘r‘ la requerida
Lo raro del operador ~> es que a la versión requerida le hace un bump
y el código de esto está en otro fichero:
$ mate rubygems/version.rb
Aquà lo pego:
# Return a new version object where the next to the last revision # number is one greater. (e.g. 5.3.1 => 5.4) def bump ints = build_array_from_version_string ints.pop if ints.size > 1 ints[-1] += 1 self.class.new(ints.join(".")) end
Al parecer a la versión requerida en la aplicación, en este caso ‘2.2.6‘, le hace un bump y la deja en ‘2.3‘ y por lo tanto la
condición:
'2.3.6' < '2.3'
No se cumple .. como podemos comprobar aquÃ:
irb> >> req = Gem::Requirement.create("~> 2.2.3") >> req.satisfied_by?( Gem::Version.new('2.3.6') ) => false >> req.satisfied_by?( Gem::Version.new('2.2.6') ) => true >> req.satisfied_by?( Gem::Version.new('2.1.6') ) => false
Lo que parece que quiere el operador ~> es que la gema disponible esté
en la misma familia X.X que la gema requerida.
Hasta aquà he llegado. Si por favor conoces la documentación oficial donde se explica pásame el link para darme bien de tollejas.