Les traits cachés de Ruby

Poursuivre les fonctionnalités Cachées de ..."mème, partageons les caractéristiques moins connues mais utiles du langage de programmation Ruby.

essayez de limiter cette discussion avec core Ruby, sans aucun truc de Ruby on Rails.

voir aussi:

(s'il vous Plaît, un fonctionnalité cachée par réponse.)

Merci

160
demandé sur squadette 2008-09-15 19:34:28
la source

30 ответов

From Ruby 1.9 Proc# = = = est un alias à Proc # call, ce qui signifie que les objets Proc peuvent être utilisés dans des déclarations comme so:

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
80
répondu Farrel 2010-12-09 00:15:52
la source

Peter Cooper a une bonne liste de Ruby tricks. Peut-être que son préféré est de permettre à la fois les articles individuels et les collections d'être énumérés. (C'est traiter un non-objet de collection comme une collection contenant cet objet.) Il ressemble à ceci:

[*items].each do |item|
  # ...
end
76
répondu James A. Rosen 2008-09-15 20:31:32
la source

Je ne sais pas à quel point c'est caché, mais je l'ai trouvé utile quand j'ai besoin de faire un hachage à partir d'un tableau unidimensionnel:

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

Hash[*fruit]    
=> {"apple"=>"red", "banana"=>"yellow"}
64
répondu astronautism 2008-09-16 11:53:31
la source

un truc que j'aime est d'utiliser l'extension splat ( * ) sur des objets autres que des tableaux. Voici un exemple sur une correspondance d'expression régulière:

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

autres exemples:

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

Job = Struct.new(:name, :occupation)
tom = Job.new("Tom", "Developer")
name, occupation = *tom
54
répondu tomafro 2011-04-02 05:00:16
la source

Wow, personne n'a mentionné l'opérateur de flip flop:

1.upto(100) do |i|
  puts i if (i == 3)..(i == 15)
end
52
répondu Konstantin Haase 2010-06-16 19:23:36
la source

l'une des choses les plus cool de ruby est que vous pouvez appeler des méthodes et exécuter du code dans des endroits sur lesquels d'autres langues fronceraient les sourcils, comme dans les définitions de méthodes ou de classes.

par exemple, pour créer une classe qui a une superclasse inconnue jusqu'à l'exécution, c'est-à-dire est aléatoire, vous pouvez faire ce qui suit:

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

end

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

Cela utilise le 1.9 Array#sample méthode (1.8.7-seulement, voir Array#choice ), et l'exemple est assez artificiel, mais vous pouvez voir les pouvoir ici.

un autre exemple cool est la possibilité de mettre des valeurs de paramètres par défaut qui ne sont pas fixes (comme d'autres langues le demandent souvent):

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

bien sûr, le problème avec le premier exemple est qu'il est évalué à la définition de temps, pas de temps d'appel. Donc, une fois qu'une superclasse a été choisie, elle reste cette superclasse pour le reste du programme.

cependant, dans le second exemple, chaque fois que vous appelez do_something_at , la variable at sera le moment où la méthode a été appelée (Eh bien, très proche de lui)

49
répondu bjeanes 2012-01-08 02:50:54
la source

une autre petite caractéristique - convertir un Fixnum dans n'importe quelle base jusqu'à 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"

et comme Huw Walters a commenté, convertir l'autre voie est tout aussi simple:

>> "kf12oi".to_i(36)
=> 1234567890
47
répondu tomafro 2011-07-19 21:41:45
la source

Hashes avec des valeurs par défaut! Un tableau dans ce cas.

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

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

très utile en métaprogrammation.

40
répondu August Lilleaas 2009-06-30 09:09:36
la source

télécharger Ruby 1.9 source, et la question make golf , alors vous pouvez faire des choses comme ceci:

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"

lire le golf_prelude.c pour des choses plus soignées se cacher.

39
répondu manveru 2008-09-15 19:49:07
la source

un autre ajout amusant dans la fonctionnalité 1.9 Proc est Proc#curry qui vous permet de transformer un proc acceptant n arguments en un acceptant n-1. = = = Tip I mentioned above:

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
38
répondu Farrel 2008-09-16 11:45:35
la source

opérateurs booléens sur valeurs non booléennes.

&& et ||

les deux renvoient la valeur de la dernière expression évaluée.

C'est pourquoi le ||= mettra à jour la variable avec l'expression valeur retournée sur le côté droit si la variable n'est pas définie. Cela n'est pas explicitement documenté, mais de notoriété publique.

cependant le &&= n'est pas très répandu connu sur.

string &&= string + "suffix"

est l'équivalent de

if string
  string = string + "suffix"
end

c'est très pratique pour les opérations destructives qui ne devraient pas se poursuivre si la variable n'est pas définie.

35
répondu EmFi 2010-04-02 22:57:12
la source

le symbole#to_proc fonction que les Rails fournit est vraiment cool.

au lieu de

Employee.collect { |emp| emp.name }

vous pouvez écrire:

Employee.collect(&:name)
29
répondu hoyhoy 2008-09-16 04:22:09
la source

un dernier one-in ruby vous pouvez utiliser n'importe quel caractère que vous voulez pour délimiter les chaînes. Prenez le code suivant:

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

si vous ne voulez pas échapper aux guillemets dans la chaîne, vous pouvez simplement utiliser un délimiteur différent:

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

en plus d'éviter d'avoir à échapper aux délimiteurs, vous pouvez utiliser ces délimiteurs pour de plus belles chaînes multilignes:

sql = %{
    SELECT strings 
    FROM complicated_table
    WHERE complicated_condition = '1'
}
28
répondu tomafro 2008-09-17 22:40:01
la source

je trouve que l'utilisation de la commande define_method pour générer dynamiquement des méthodes est assez intéressante et pas aussi bien connue. Par exemple:

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

le code ci-dessus utilise la commande 'define_method' pour créer dynamiquement les méthodes" press1 "à" press9."Plutôt que de taper les 10 méthodes qui contiennent essentiellement le même code, la commande define method est utilisée pour générer ces méthodes à la volée si nécessaire.

26
répondu CodingWithoutComments 2008-09-15 20:01:21
la source

utilisez un objet Range comme une liste paresseuse infinie:

Inf = 1.0 / 0

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

plus d'informations ici: http://banisterfiend.wordpress.com/2009/10/02/wtf-infinite-ranges-in-ruby /

26
répondu horseyguy 2009-11-30 06:30:00
la source

module_function

modules méthodes qui sont déclarés comme module_function vont créer des copies d'eux-mêmes comme privés instance méthodes dans la classe qui comprend le Module:

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 vous utilisez module_function sans aucun argument, alors toute méthode de module qui vient après la déclaration module_function deviendra automatiquement module_functions m'.

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!'
23
répondu newtonapple 2008-09-23 12:18:13
la source

Court injecter, comme tel:

somme de la fourchette:

(1..10).inject(:+)
=> 55
23
répondu user130730 2009-06-30 03:05:14
la source

Avertissement: cet article a été voté #1 Plus Horribles de Hack de 2008 , donc à utiliser avec précaution. En fait, l'éviter comme la peste, mais il est très certainement Caché Ruby.

Superators Ajouter de Nouveaux Opérateurs à Ruby

vous avez déjà voulu un opérateur de poignée de main super secret pour une opération unique dans votre code? Comme jouer au code de golf? Essayez les opérateurs comme -~+~- ou <--- Ce dernier est utilisé dans le exemples pour inverser l'ordre d'un article.

Je n'ai rien à voir avec le Superators Project au-delà de l'admirer.

21
répondu Captain Hammer 2008-09-16 07:08:32
la source

je suis en retard à la fête, mais:

vous pouvez facilement prendre deux tableaux de longueur égale et les transformer en un hachage avec un tableau fournissant les clés et l'autre les valeurs:

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

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

(cela fonctionne parce que le tableau # zip "zips" up les valeurs des deux tableaux:

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

et Hash[] peut prendre juste un tel tableau. J'ai vu des gens le faire aussi:

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

Qui donne le même résultat, mais l'éclaboussure et l'aplatissement sont tout à fait inutiles--peut-être qu'ils ne l'étaient pas dans le passé?)

19
répondu Jordan Running 2009-10-09 01:29:33
la source

Auto-vivifiant hachages dans 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 } } }

ça peut être très pratique.

19
répondu Trevoke 2010-01-25 17:13:23
la source

destruction D'un réseau

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

où:

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

en utilisant cette technique, nous pouvons utiliser l'assignation simple pour obtenir les valeurs exactes que nous voulons de tableau imbriqué de n'importe quelle profondeur.

16
répondu horseyguy 2010-09-29 20:43:06
la source

Class.new()

créer une nouvelle classe à l'exécution. L'argument peut être une classe pour dériver, et le bloc est le corps de classe. Vous pouvez également regarder const_set/const_get/const_defined? pour obtenir votre nouvelle classe correctement enregistré, de sorte que inspect imprime un nom au lieu d'un nombre.

pas quelque chose dont vous avez besoin tous les jours, mais assez pratique quand vous le faites.

15
répondu Justin Love 2008-10-22 06:28:07
la source

créer un tableau de nombres consécutifs:

x = [*0..5]

ensembles de x à [0, 1, 2, 3, 4, 5]

13
répondu horseyguy 2009-08-04 00:44:51
la source

une grande partie de la magie que vous voyez dans Rubyland a à voir avec la métaprogrammation, qui est simplement l'écriture de code qui écrit le code pour vous. Les attr_accessor , attr_reader et attr_writer de Ruby sont tous de simples métaprogrammations , en ce qu'ils créent deux méthodes en une ligne, suivant un modèle standard. Les Rails font beaucoup de métaprogrammation avec leurs méthodes de gestion des relations comme has_one et belongs_to .

mais il est assez simple de créer votre propre des astuces de programmation utilisant class_eval pour exécuter du code dynamiquement écrit.

l'exemple suivant permet à un objet wrapper de transmettre certaines méthodes à un objet interne:

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"]

La méthode Wrapper.forwards prend des symboles pour les noms de méthodes et les stocke dans le "151980920 tableau. Puis, pour chacun de ceux donnés ,nous utilisons define_method pour créer une nouvelle méthode dont la tâche est d'envoyer le message, y compris tous les disputes et blocages.

Une grande ressource pour la métaprogrammation questions est Pourquoi le Lucky Stiff "Voir la Métaprogrammation Clairement" .

13
répondu TALlama 2011-03-12 20:48:02
la source

utilisez tout ce qui répond à ===(obj) pour les comparaisons de cas:

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 (et donc Class ), Regexp , Date , et beaucoup d'autres classes définissent une méthode d'instance :===(other), et peuvent toutes être utilisées.

merci à Farrel pour le rappel de Proc#call étant alias Proc#=== dans Ruby 1.9.

12
répondu James A. Rosen 2017-05-23 15:10:08
la source

le binaire" ruby " (au moins IRM) supporte beaucoup de commutateurs qui ont rendu les monocouches perl très populaires.

Importants d'entre eux:

  • - n établit une boucle externe avec just "gets" - qui fonctionne magiquement avec un nom de fichier donné ou STDIN, définissant chaque ligne lue en $ _
  • - p similaire à-n mais avec un put s automatique à la fin de chaque itération de boucle
  • -un appel Automatique .Split sur chaque ligne d'entrée, stockée en $f
  • -j'En-lieu de modifier les fichiers d'entrée
  • - l appel automatique à .chomp sur l'entrée
  • -e Exécuter un morceau de code
  • - C Vérifier le code source
  • - w avec Avertissements

quelques exemples:

# 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

N'hésitez pas à google "ruby un-liners" et "perl un-liners" pour des tonnes d'exemples plus utilisables et pratiques. Il vous permet essentiellement d'utiliser ruby comme un remplacement assez puissant à awk et sed.

11
répondu minaguib 2010-01-02 23:59:28
la source

la méthode send () est une méthode à usage général qui peut être utilisée sur N'importe quelle classe ou objet de Ruby. Si elle n'est pas annulée, send() accepte une chaîne de caractères et appelle le nom de la méthode dont elle est passée. Par exemple, si l'utilisateur clique sur le bouton "Clr", la chaîne "press_clear" sera envoyée à la méthode send() et la méthode "press_clear" sera appelée. La méthode send () permet une façon amusante et dynamique d'appeler des fonctions dans 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

je parle plus de cette fonctionnalité dans les chaussures de Blogging: L'Application Simple-Calc

10
répondu CodingWithoutComments 2008-09-15 19:53:01
la source

tromper une classe ou un module en disant qu'il a exigé quelque chose qu'il n'a vraiment pas exigé:

$" << "something"

ceci est utile par exemple lorsque l'exigence A nécessite B mais que nous n'avons pas besoin de B dans notre code (et A ne l'utilisera pas non plus dans notre code):

par exemple, bdrb_test_helper requires 'test/spec' de Backgrounddrb, mais vous ne l'utilisez pas du tout, donc dans votre code:

$" << "test/spec"
require File.join(File.dirname(__FILE__) + "/../bdrb_test_helper")
9
répondu olegueret 2008-09-16 03:51:16
la source

Fixnum#to_s(base) peut être vraiment utile dans certains cas. Un de ces cas est la génération de jetons aléatoires (pseudo)uniques en convertissant le nombre aléatoire en chaîne en utilisant la base de 36.

jeton de longueur 8:

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

jeton de longueur 6:

rand(36**6).to_s(36) => "bvhl8d"
rand(36**6).to_s(36) => "lb7tis"
rand(36**6).to_s(36) => "ibwgeh"
9
répondu sickill 2010-02-26 13:05:21
la source

définition d'une méthode qui accepte n'importe quel nombre de paramètres et les écarte juste tous

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

la méthode ci - dessus hello n'a besoin que de puts "hello" sur l'écran et d'appeler super - mais puisque la superclasse hello définit des paramètres, elle doit aussi - cependant, puisqu'elle n'a pas réellement besoin d'utiliser les paramètres elle-même-elle n'a pas à leur donner un nom.

9
répondu horseyguy 2010-10-01 01:05:44
la source

Autres questions sur ruby hidden-features