Características ocultas de Ruby

160

Continuando con el meme "Características ocultas de ...", compartamos las características menos conocidas pero útiles del lenguaje de programación Ruby.

Intenta limitar esta discusión con el núcleo de Ruby, sin nada de Ruby on Rails.

Ver también:

(Por favor, solo una función oculta por respuesta).

Gracias

squadette
fuente
debería ser wiki comunitario
SilentGhost

Respuestas:

80

De Ruby 1.9 Proc # === es un alias para la llamada Proc #, lo que significa que los objetos Proc se pueden usar en declaraciones de caso como esta:

def multiple_of(factor)
  Proc.new{|product| product.modulo(factor).zero?}
end

case number
  when multiple_of(3)
    puts "Multiple of 3"
  when multiple_of(7)
    puts "Multiple of 7"
end
Farrel
fuente
1
En realidad, escribí una gema en un punto para hacer esto, pero mi código era (a) un desastre y (b) lento. Estoy muy contento de que la funcionalidad lo haya convertido en núcleo.
James A. Rosen
76

Peter Cooper tiene una buena lista de trucos de Ruby. Quizás mi favorito es permitir que se enumeren artículos individuales y colecciones. (Es decir, trate un objeto que no sea de colección como una colección que contenga solo ese objeto). Se ve así:

[*items].each do |item|
  # ...
end
James A. Rosen
fuente
38
Una forma más explícita (y por lo tanto más agradable) de esto es Array (items) .each
mislav
Si itemses una cadena, no tiene que encerrarla con [* ...]. String.each no itera sobre los caracteres como algunos pueden esperar. Simplemente regresa al bloque.
mxcl
¿De qué serviría esto alguna vez? Sólo curioso.
Ed S.
1
@Ed: es bueno si está escribiendo un método y desea permitir que el usuario del método pase una lista varargs o una matriz.
James A. Rosen
64

No sé qué tan oculto está esto, pero lo he encontrado útil cuando necesito hacer un hash de una matriz unidimensional:

fruit = ["apple","red","banana","yellow"]
=> ["apple", "red", "banana", "yellow"]

Hash[*fruit]    
=> {"apple"=>"red", "banana"=>"yellow"}
astronautismo
fuente
Tenga en cuenta que Hash[ [["apple","red"], ["banana","yellow"] ]produce el mismo resultado.
Marc-André Lafortune
54

Un truco que me gusta es usar el *expansor splat ( ) en objetos que no sean Arrays. Aquí hay un ejemplo en una coincidencia de expresión regular:

match, text, number = *"Something 981".match(/([A-z]*) ([0-9]*)/)

Otros ejemplos incluyen:

a, b, c = *('A'..'Z')

Job = Struct.new(:name, :occupation)
tom = Job.new("Tom", "Developer")
name, occupation = *tom
tomafro
fuente
13
Por cierto, para los curiosos, esto funciona al llamar implícitamente a to_a en el objetivo del símbolo.
Bob Aman
1
Si no estás interesado en el partido, puedes tenerlo text, number = *"text 555".match(/regexp/)[1..-1].
Andrew Grimm
text, number = "Something 981".scan(/([A-z]*) ([0-9]*)/).flatten.map{|m| Integer(m) rescue m}
Jonas Elfström
77
Ambos buenos trucos, pero tiene que haber un punto en el que sea demasiada magia, ¿verdad?
tomafro
1
@ Andrew, ¿consideró que ese partido puede devolver nada? nil no tiene método []
Alexey
52

Wow, nadie mencionó el operador de flip flop:

1.upto(100) do |i|
  puts i if (i == 3)..(i == 15)
end
Konstantin Haase
fuente
11
Bien ... alguien tendrá que explicarme esto. Funciona, pero no puedo entender por qué.
Bob Aman
12
El operador de flip flop es un estado completo si. Su estado cambia a verdadero tan pronto como i == 3cambia a falso después de i != 3 y i == 15. Similar a un flip-flop: en.wikipedia.org/wiki/Flip-flop_%28electronics%29
Konstantin Haase
1
No llamaría exactamente a esto una característica oculta, tan molesta. Recuerdo la primera vez que me presentaron en #Ruby en Freenode, hace años; Básicamente he usado todas las características de Ruby en algún momento, excepto esta.
ELLIOTTCABLE
1
No lo llamaría una molestia, es algo que no has usado. Lo uso y puede reducir muy bien el código, especialmente cuando estoy tomando bloques de líneas de archivos basados ​​en algunos criterios.
The Tin Man
49

Una de las cosas interesantes de Ruby es que puede llamar a métodos y ejecutar código en lugares donde otros lenguajes estarían mal, como en definiciones de clase o método.

Por ejemplo, para crear una clase que tiene una superclase desconocida hasta el tiempo de ejecución, es decir, es aleatorio, puede hacer lo siguiente:

class RandomSubclass < [Array, Hash, String, Fixnum, Float, TrueClass].sample

end

RandomSubclass.superclass # could output one of 6 different classes.

Esto usa el 1.9 Array#sample método (solo en 1.8.7, ver Array#choice), y el ejemplo es bastante ingenioso, pero puedes ver el poder aquí.

Otro buen ejemplo es la capacidad de poner valores de parámetros predeterminados que no son fijos (como suelen exigir otros idiomas):

def do_something_at(something, at = Time.now)
   # ...
end

Por supuesto, el problema con el primer ejemplo es que se evalúa en el momento de la definición, no en el momento de la llamada. Entonces, una vez que se ha elegido una superclase, se mantiene esa superclase por el resto del programa.

Sin embargo, en el segundo ejemplo, cada vez que llame do_something_at, la atvariable será la hora en que se llamó al método (bueno, muy, muy cerca de él)

bjeanes
fuente
2
Nota: ActiveSupport proporciona Array # rand, que puede usar fuera de Rails tan fácilmente comorequire 'activesupport'
rfunduk
La opción de matriz # está en 1.8.7
Josh Lee
24
¡La opción de matriz # es solo 1.8.7 ! No lo use, se fue en 1.9 y se irá en 1.8.8. Use #sample
Marc-André Lafortune el
python: class DictList ([dict, list] [random.randint (0,1)]): pasar
Anurag Uniyal
def do_something_at (algo, en = lambda {Time.now}) at.call #now asignar dinámicamente el final del tiempo
Jack Kinsella
47

Otra característica pequeña: convierte un Fixnuma cualquier base hasta 36:

>> 1234567890.to_s(2)
=> "1001001100101100000001011010010"

>> 1234567890.to_s(8)
=> "11145401322"

>> 1234567890.to_s(16)
=> "499602d2"

>> 1234567890.to_s(24)
=> "6b1230i"

>> 1234567890.to_s(36)
=> "kf12oi"

Y como ha comentado Huw Walters, la conversión a la inversa es igual de simple:

>> "kf12oi".to_i(36)
=> 1234567890
tomafro
fuente
1
Y para completar, String#to_s(base)se puede utilizar para convertir de nuevo a un número entero; "1001001100101100000001011010010".to_i(2), "499602d2".to_i(16)etc todos devuelven el original Fixnum.
Huw Walters
40

¡Hashes con valores predeterminados! Una matriz en este caso.

parties = Hash.new {|hash, key| hash[key] = [] }
parties["Summer party"]
# => []

parties["Summer party"] << "Joe"
parties["Other party"] << "Jane"

Muy útil en metaprogramación.

August Lilleaas
fuente
1
si cierto. El hash de Ruby puede aceptar el operador '<<' si ya hay un valor predeterminado asignado con '=' (no me importa incluso si es una asignación vacía) de lo contrario, el hash no aceptará '<<'. CMIIW
mhd
39

Descargue la fuente Ruby 1.9, y emítela make golf, luego puede hacer cosas como esta:

make golf

./goruby -e 'h'
# => Hello, world!

./goruby -e 'p St'
# => StandardError

./goruby -e 'p 1.tf'
# => 1.0

./goruby19 -e 'p Fil.exp(".")'
"/home/manveru/pkgbuilds/ruby-svn/src/trunk"

Lee las golf_prelude.ccosas más ordenadas que se esconden.

manveru
fuente
38

Otra adición divertida en la funcionalidad 1.9 Proc es Proc # curry, que le permite convertir un Proc que acepta n argumentos en uno que acepta n-1. Aquí se combina con el consejo Proc # === que mencioné anteriormente:

it_is_day_of_week = lambda{ |day_of_week, date| date.wday == day_of_week }
it_is_saturday = it_is_day_of_week.curry[6]
it_is_sunday = it_is_day_of_week.curry[0]

case Time.now
when it_is_saturday
  puts "Saturday!"
when it_is_sunday
  puts "Sunday!"
else
  puts "Not the weekend"
end
Farrel
fuente
35

Operadores booleanos en valores no booleanos.

&& y ||

Ambos devuelven el valor de la última expresión evaluada.

Es por eso ||=que actualizará la variable con la expresión de valor devuelto en el lado derecho si la variable no está definida. Esto no está explícitamente documentado, pero es de conocimiento común.

Sin embargo, el &&=no es tan conocido.

string &&= string + "suffix"

es equivalente a

if string
  string = string + "suffix"
end

Es muy útil para operaciones destructivas que no deberían continuar si la variable no está definida.

EmFi
fuente
2
Más precisamente, string &&= string + "suffix" es equivalente a string = string && string + "suffix". Eso &&y ||devolver su segundo argumento se discute en PickAx, p. 154 (Parte I - Facetas de Ruby, Expresiones, Ejecución condicional).
Richard Michael
29

La función Symbol # to_proc que proporciona Rails es realmente genial.

En vez de

Employee.collect { |emp| emp.name }

Puedes escribir:

Employee.collect(&:name)
hoyhoy
fuente
Esto es, aparentemente, un "orden de magnitud más lento" que usar un bloque. igvita.com/2008/07/08/6-optimization-tips-for-ruby-mri
Charles Roper
Lo probé y descubrí que no había una diferencia significativa entre los dos. No estoy seguro de dónde vino este material del "orden de magnitud". (Usando Ruby 1.8.7)
Matt Grande el
1
Hacer esto fuera de Rails también es útil y se puede hacer require 'activesupport'ya que de ahí es de donde provienen la mayoría de estos ayudantes.
rfunduk
8
esto solía ser lento debido a la implementación de active_support, es decir, aceptaba múltiples argumentos para que pudiera hacer una mierda genial como (1..10) .inject &: *, pero el caso de uso principal a menudo solo llamaba a un método en cada miembro de un colección por ejemplo% w (el zorro marrón rápido) .map &: upcase. a partir de 1.8.7 es core ruby ​​y el rendimiento es razonable.
Steve Graham
44
@thenduks: Y se puede hacer sin la ayuda de activeiveupport en ruby ​​1.8.7 y 1.9.
Andrew Grimm
28

Una última: en ruby ​​puedes usar cualquier personaje que quieras delimitar cadenas. Toma el siguiente código:

message = "My message"
contrived_example = "<div id=\"contrived\">#{message}</div>"

Si no desea escapar de las comillas dobles dentro de la cadena, simplemente puede usar un delimitador diferente:

contrived_example = %{<div id="contrived-example">#{message}</div>}
contrived_example = %[<div id="contrived-example">#{message}</div>]

Además de evitar tener que escapar de los delimitadores, puede usar estos delimitadores para cadenas multilíneas más bonitas:

sql = %{
    SELECT strings 
    FROM complicated_table
    WHERE complicated_condition = '1'
}
tomafro
fuente
19
No es ningún personaje, pero sigue siendo genial. También funciona con otros literales:% () /% {} /% [] /% <> /% || % r () /% r {} /% r [] /% r <> /% r || % w () /% w {} /% w [] /% w <> /% w ||
Bo Jeanes
También está la sintaxis del documento herenow: << BLOCK ... BLOCK, que me gusta usar para cosas como sentencias SQL multilínea, etc.
Martin T.
26

El uso del comando define_method para generar dinámicamente métodos es bastante interesante y no tan conocido. Por ejemplo:

((0..9).each do |n|
    define_method "press_#{n}" do
      @number = @number.to_i * 10 + n
    end
  end

El código anterior usa el comando 'define_method' para crear dinámicamente los métodos "press1" a través de "press9". En lugar de escribir los 10 métodos que contienen básicamente el mismo código, el comando definir método se usa para generar estos métodos sobre la marcha según sea necesario.

CodingWithoutComments
fuente
44
El único problema con define_method es que no permite que se pasen bloques como parámetros en ruby ​​1.8. Vea esta publicación de blog para una solución alternativa.
Andrew Grimm
26

Use un objeto Range como una lista perezosa infinita:

Inf = 1.0 / 0

(1..Inf).take(5) #=> [1, 2, 3, 4, 5]

Más información aquí: http://banisterfiend.wordpress.com/2009/10/02/wtf-infinite-ranges-in-ruby/

horseyguy
fuente
Lazy_select en el artículo vinculado es muy ordenado.
Joseph Weissman el
Esto es realmente asombroso. Me gusta cómo Infinity es un flotante, de esa manera cuando probé esto: (-Inf..Inf) .take (4) planteó un (lógicamente consistente) no puede iterar desde un error de flotante. : D
zachaysan
23

función_módulo

Los métodos de módulo que se declaran como module_function crearán copias de sí mismos como métodos de instancia privada en la clase que incluye el Módulo:

module M
  def not!
    'not!'
  end
  module_function :not!
end

class C
  include M

  def fun
    not!
  end
end

M.not!     # => 'not!
C.new.fun  # => 'not!'
C.new.not! # => NoMethodError: private method `not!' called for #<C:0x1261a00>

Si usa module_function sin ningún argumento, cualquier método de módulo que venga después de la declaración module_function se convertirá automáticamente en module_functions.

module M
  module_function

  def not!
    'not!'
  end

  def yea!
    'yea!'
  end
end


class C
  include M

  def fun
    not! + ' ' + yea!
  end
end
M.not!     # => 'not!'
M.yea!     # => 'yea!'
C.new.fun  # => 'not! yea!'
newtonapple
fuente
44
Si solo desea declarar métodos privados en módulos, simplemente use la palabra clave privada. Además de hacer que el método sea privado en las clases que incluyen el módulo, module_function copia el método en la instancia del módulo. En la mayoría de los casos, esto no es lo que quieres.
tomafro 03 de
Sé que puedes usar privado. Pero esta es una pregunta sobre las características ocultas de Ruby. Y, creo que la mayoría de la gente nunca ha oído hablar de module_function (incluido yo mismo) hasta que lo ven en el documento y comienzan a jugar con él.
newtonapple
Una alternativa al uso module_function(segunda forma) es usar extend self(que se ve muy bien: D)
J -_- L
23

Inyección corta, como tal:

Suma de rango:

(1..10).inject(:+)
=> 55
usuario130730
fuente
2
Vale la pena señalar que necesita Ruby 1.9 o Rails con Ruby 1.8 para que esto funcione.
mxcl
1
@Max Howell: o require 'backports':-)
Marc-André Lafortune
1
¿No es esto un duplicado de la respuesta de hoyhoy?
Andrew Grimm
21

Advertencia: este artículo fue votado como el # 1 Hack más horrendo de 2008 , así que úsalo con cuidado. En realidad, evítalo como la peste, pero sin duda es Hidden Ruby.

Superators agrega nuevos operadores a Ruby

¿Alguna vez quisiste un operador de apretón de manos súper secreto para una operación única en tu código? ¿Te gusta jugar al golf en código? Pruebe operadores como - ~ + ~ - o <--- Ese último se usa en los ejemplos para invertir el orden de un elemento.

No tengo nada que ver con el Proyecto Superators más allá de admirarlo.

Capitán martillo
fuente
19

Llego tarde a la fiesta, pero:

Puede tomar fácilmente dos matrices de igual longitud y convertirlas en un hash con una matriz que proporciona las claves y la otra los valores:

a = [:x, :y, :z]
b = [123, 456, 789]

Hash[a.zip(b)]
# => { :x => 123, :y => 456, :z => 789 }

(Esto funciona porque la matriz # zip "comprime" los valores de las dos matrices:

a.zip(b)  # => [[:x, 123], [:y, 456], [:z, 789]]

Y Hash [] puede tomar tal arreglo. He visto a personas hacer esto también:

Hash[*a.zip(b).flatten]  # unnecessary!

Lo que produce el mismo resultado, pero el aplastamiento y el aplanamiento son totalmente innecesarios, ¿tal vez no estaban en el pasado?)

Jordan Running
fuente
3
De hecho, esto estuvo indocumentado durante mucho tiempo (ver redmine.ruby-lang.org/issues/show/1385 ). Tenga en cuenta que este nuevo formulario es nuevo para Ruby 1.8.7
Marc-André Lafortune
19

Hashes auto vivificantes en Ruby

def cnh # silly name "create nested hash"
  Hash.new {|h,k| h[k] = Hash.new(&h.default_proc)}
end
my_hash = cnh
my_hash[1][2][3] = 4
my_hash # => { 1 => { 2 => { 3 =>4 } } }

Esto puede ser muy útil.

Trevoke
fuente
1
Lo envolvería en un módulo para tener la misma sensación de hash init nativo:module InfHash; def self.new; Hash.new {|h,k| h[k] = Hash.new(&h.default_proc)}; end; end
asaaki
16

Destruyendo una matriz

(a, b), c, d = [ [:a, :b ], :c, [:d1, :d2] ]

Dónde:

a #=> :a
b #=> :b
c #=> :c
d #=> [:d1, :d2]

Con esta técnica, podemos usar una asignación simple para obtener los valores exactos que deseamos de una matriz anidada de cualquier profundidad.

horseyguy
fuente
15

Class.new()

Crea una nueva clase en tiempo de ejecución. El argumento puede ser una clase para derivar, y el bloque es el cuerpo de la clase. También es posible que desee mirar const_set/const_get/const_defined?para registrar su nueva clase correctamente, para que inspectimprima un nombre en lugar de un número.

No es algo que necesite todos los días, pero es bastante útil cuando lo necesita.

Sólo en el amor
fuente
1
MyClass = Class.new Array do; def hi; 'hi'; end; endparece ser equivalente a class MyClass < Array; def hi; 'hi'; end; end.
yfeldblum
1
Probablemente más cierto de lo que había pensado. Incluso parece que puede heredar de una variable en lugar de solo una constante. Sin embargo, la versión azucarada (segundo) no parece funcionar si necesita construir el nombre de la clase en tiempo de ejecución. (Baring eval, por supuesto.)
Justin Love
Esta técnica está bastante bien descrita en el libro Metaprogramming Ruby .
Paul Pladijs
13

crear una matriz de números consecutivos:

x = [*0..5]

establece x en [0, 1, 2, 3, 4, 5]

horseyguy
fuente
Sí, pero no es tan corto y dulce;)
horseyguy
2
la brevedad es objetiva, la legibilidad es cuestión de gustos y experiencia
Alexey
El *operador splat ( ) básicamente llama de to_atodos modos.
Matheus Moreira
13

Gran parte de la magia que ves en Rubyland tiene que ver con la metaprogramación, que es simplemente escribir código que escriba código para ti. Ruby attr_accessor, attr_readery attr_writerson sencillas metaprogramming, en el que crean dos métodos en una sola línea, siguiendo un patrón estándar. Rails realiza una gran cantidad de metaprogramación con sus métodos de gestión de relaciones como has_oney belongs_to.

Pero es bastante simple crear tus propios trucos de metaprogramación class_evalpara ejecutar código escrito dinámicamente.

El siguiente ejemplo permite que un objeto contenedor reenvíe ciertos métodos a un objeto interno:

class Wrapper
  attr_accessor :internal

  def self.forwards(*methods)
    methods.each do |method|
      define_method method do |*arguments, &block|
        internal.send method, *arguments, &block
      end
    end
  end

  forwards :to_i, :length, :split
end

w = Wrapper.new
w.internal = "12 13 14"
w.to_i        # => 12
w.length      # => 8
w.split('1')  # => ["", "2 ", "3 ", "4"]

El método Wrapper.forwardstoma símbolos para los nombres de los métodos y los almacena en la methodsmatriz. Luego, para cada uno de los dados, usamosdefine_method para crear un nuevo método cuyo trabajo es enviar el mensaje, incluyendo todos los argumentos y bloques.

Un gran recurso para los problemas de metaprogramación es por qué "Lucky View Metaprogramming Clearing" de Lucky Stiff .

TALlama
fuente
Deseo sumergirme primero en la metaprogramación en rubí. ¿Podría proporcionar algunas referencias para comenzar con él (aparte del enlace dado)? Los libros también lo harán. Gracias.
Chirantan
La serie de videocasting de PragProg "The Ruby Object Model and Metaprogramming" es una buena introducción a la meta programación usando ruby: pragprog.com/screencasts/v-dtrubyom/…
caffo
@Chirantan, mira Metaprogramming Ruby .
Paul Pladijs
12

use cualquier cosa que responda a las ===(obj)comparaciones de casos:

case foo
when /baz/
  do_something_with_the_string_matching_baz
when 12..15
  do_something_with_the_integer_between_12_and_15
when lambda { |x| x % 5 == 0 }
  # only works in Ruby 1.9 or if you alias Proc#call as Proc#===
  do_something_with_the_integer_that_is_a_multiple_of_5
when Bar
  do_something_with_the_instance_of_Bar
when some_object
  do_something_with_the_thing_that_matches_some_object
end

Module(y por tanto Class), Regexp,Date , y muchas otras clases definen un método de instancia: === (otro), y todos se pueden usar.

Gracias a Farrel por el recordatorio de Proc#calltener un alias como Proc#===en Ruby 1.9.

James A. Rosen
fuente
11

El binario "ruby" (al menos MRI) es compatible con muchos de los interruptores que hicieron que perl one-liners sea bastante popular.

Los significativos:

  • -n Configura un bucle externo con solo "gets", que funciona mágicamente con un nombre de archivo dado o STDIN, configurando cada línea de lectura en $ _
  • -p Similar a -n pero con un cambio automático put s al final de cada iteración del ciclo
  • -una llamada automática a .split en cada línea de entrada, almacenada en $ F
  • -i Edición de archivos de entrada en el lugar
  • -l Llamada automática a .chomp en la entrada
  • -e Ejecuta un fragmento de código
  • -c Verificar el código fuente
  • -w Con advertencias

Algunos ejemplos:

# Print each line with its number:
ruby -ne 'print($., ": ", $_)' < /etc/irbrc

# Print each line reversed:
ruby -lne 'puts $_.reverse' < /etc/irbrc

# Print the second column from an input CSV (dumb - no balanced quote support etc):
ruby -F, -ane 'puts $F[1]' < /etc/irbrc

# Print lines that contain "eat"
ruby -ne 'puts $_ if /eat/i' < /etc/irbrc

# Same as above:
ruby -pe 'next unless /eat/i' < /etc/irbrc

# Pass-through (like cat, but with possible line-end munging):
ruby -p -e '' < /etc/irbrc

# Uppercase all input:
ruby -p -e '$_.upcase!' < /etc/irbrc

# Same as above, but actually write to the input file, and make a backup first with extension .bak - Notice that inplace edit REQUIRES input files, not an input STDIN:
ruby -i.bak -p -e '$_.upcase!' /etc/irbrc

Siéntase libre de google "ruby one-liners" y "perl one-liners" para obtener toneladas de ejemplos más útiles y prácticos. Básicamente, le permite usar ruby ​​como un reemplazo bastante poderoso para awk y sed.

minaguib
fuente
10

El método send () es un método de propósito general que se puede usar en cualquier clase u objeto en Ruby. Si no se reemplaza, send () acepta una cadena y llama al nombre del método cuya cadena se pasa. Por ejemplo, si el usuario hace clic en el botón "Clr", la cadena 'press_clear' se enviará al método send () y se llamará al método 'press_clear'. El método send () permite una forma divertida y dinámica de llamar a funciones en Ruby.

 %w(7 8 9 / 4 5 6 * 1 2 3 - 0 Clr = +).each do |btn|
    button btn, :width => 46, :height => 46 do
      method = case btn
        when /[0-9]/: 'press_'+btn
        when 'Clr': 'press_clear'
        when '=': 'press_equals'
        when '+': 'press_add'
        when '-': 'press_sub'
        when '*': 'press_times'
        when '/': 'press_div'
      end

      number.send(method)
      number_field.replace strong(number)
    end
  end

Hablo más sobre esta característica en Blogging Shoes: la aplicación Simple-Calc

CodingWithoutComments
fuente
Suena como una excelente manera de abrir un agujero de seguridad.
mP.
44
Usaría símbolos siempre que sea posible.
reto
9

Engaña a alguna clase o módulo diciéndole que ha requerido algo que realmente no ha requerido:

$" << "something"

Esto es útil, por ejemplo, cuando se requiere A que a su vez requiere B pero no necesitamos B en nuestro código (y A tampoco lo usará a través de nuestro código):

Por ejemplo, Backgroundrb's bdrb_test_helper requires 'test/spec', pero no lo usa en absoluto, así que en su código:

$" << "test/spec"
require File.join(File.dirname(__FILE__) + "/../bdrb_test_helper")
olegueret
fuente
¿Esto soluciona los problemas donde la gema A requiere foo-1.0.0 y la gema B requiere foo-1.0.1?
Andrew Grimm
No porque el código de "algo" no estará disponible: esto solo simula que se requiere "algo", pero realmente no lo requiere. $ "es una matriz que contiene los nombres de módulos cargados por require (se usa por require para evitar cargar módulos dos veces). Entonces, si usa esto para engañar a las gemas, se producirá un bloqueo cuando las gemas intenten usar el" algo "real código, porque no existirá. En su lugar, puede querer forzar una versión concreta de una gema (por ejemplo, foo-1.0.0), en lugar de la última: docs.rubygems.org/read/chapter/4#page71
olegueret
9

Fixnum#to_s(base)puede ser realmente útil en algún caso. Uno de estos casos es generar tokens aleatorios (pseudo) únicos al convertir un número aleatorio en una cadena utilizando la base de 36.

Ficha de longitud 8:

rand(36**8).to_s(36) => "fmhpjfao"
rand(36**8).to_s(36) => "gcer9ecu"
rand(36**8).to_s(36) => "krpm0h9r"

Ficha de longitud 6:

rand(36**6).to_s(36) => "bvhl8d"
rand(36**6).to_s(36) => "lb7tis"
rand(36**6).to_s(36) => "ibwgeh"
enfermo
fuente
9

Definir un método que acepte cualquier número de parámetros y simplemente los descarte todos

def hello(*)
    super
    puts "hello!"
end

El hellométodo anterior solo necesita aparecer puts "hello"en la pantalla y llamar super, pero dado que la superclase hellodefine los parámetros, también debe hacerlo; sin embargo, dado que en realidad no necesita usar los parámetros en sí, no tiene que darles un nombre.

horseyguy
fuente