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.
Enero 31st, 2009 at 6:06 pm
Ostias. Me viene de puta madre.
Voy a empezar a usarlo por todas partes, ya que me permite dar flexibilidad a mis gemas, siempre y cuando no haya cambios mayores (Se supone que un salto de versión es un cambio mayor, creo).
Muchas gracias.
Noviembre 27th, 2016 at 3:05 pm
Have you ever considered about including a little bit more than just your articles?
I mean, what you say is valuable and all. However think of
if you added some great pictures or videos to give your posts more,
“pop”! Your content is excellent but with images and videos, this website could undeniably be one of the best
in its niche. Fantastic blog!