Ruby'nin Gizli Özellikleri


160

"Gizli özellikleri ..." devam eden meme, Ruby programlama dilinin daha az bilinen ama yararlı özelliklerini paylaşalım.

Bu tartışmayı herhangi bir Ruby on Rails malzemesi olmadan çekirdek Ruby ile sınırlamaya çalışın.

Ayrıca bakınız:

(Lütfen, yanıt başına yalnızca bir gizli özellik.)

teşekkür ederim


topluluk wiki olmalı
SilentGhost

Yanıtlar:


80

Ruby 1.9'dan Proc # ===, Proc # çağrısının diğer adıdır; bu, Proc nesnelerinin aşağıdaki gibi durumlarda ifadelerde kullanılabileceği anlamına gelir:

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

1
Aslında bunu yapmak için bir noktada bir mücevher yazdı, ama benim kod (a) bir karışıklık ve (b) yavaş oldu. İşlevselliğin çekirdeğe dönüşmesinden çok memnunum.
James A. Rosen

76

Peter Cooper'ın Ruby hilelerinin iyi bir listesi var . Belki de onun favorisi, hem tek parçaların hem de koleksiyonların numaralandırılmasına izin vermektir. (Yani, koleksiyon olmayan bir nesneyi yalnızca bu nesneyi içeren bir koleksiyon olarak ele alın.) Şuna benzer:

[*items].each do |item|
  # ...
end

38
Bunun daha açık (ve dolayısıyla daha güzel) bir şekli Array (eşyalar) .each
mislav

Eğer itemsbir dize ise [*…] ile çevrelemeniz gerekmez. String.each, bazılarının beklediği gibi karakterler üzerinde yineleme yapmaz. Sadece bloğa geri döner.
mxcl

Bu ne işe yarar ki? Sadece merak.
Ed S.

1
@Ed: Bir yöntem yazıyorsanız ve yöntem kullanıcısının varargs listesini veya Array'ı geçirmesine izin vermek istiyorsanız iyi olur.
James A. Rosen

64

Bunun ne kadar gizli olduğunu bilmiyorum, ancak tek boyutlu bir diziden bir Hash oluşturmaya ihtiyaç duyduğumda yararlı buldum:

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

Hash[*fruit]    
=> {"apple"=>"red", "banana"=>"yellow"}

Not Hash[ [["apple","red"], ["banana","yellow"] ]aynı sonucu üretir.
Marc-André Lafortune

54

Sevdiğim bir numara, *Diziler dışındaki nesnelerde splat ( ) genişleticisini kullanmaktır . Normal ifade eşleşmesine ilişkin bir örnek:

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

Diğer örnekler:

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

Job = Struct.new(:name, :occupation)
tom = Job.new("Tom", "Developer")
name, occupation = *tom

13
Bu arada, meraklı için bu, uyarının hedefi üzerinde to_a'yı dolaylı olarak çağırarak çalışır.
Bob Aman

1
Maçla ilgilenmiyorsanız, sahip olabilirsiniz 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}
Ocak'ta Jonas Elfström

7
Her ikisi de iyi hileler, ama çok fazla büyü olduğu bir nokta olmalı, değil mi ?!
tomafro

1
@ Andrew, bu maçın nil geri dönebileceğini düşündün mü? nil yöntemi yok []
Alexey

52

Vay canına, hiç kimse flip flop operatöründen bahsetmedi:

1.upto(100) do |i|
  puts i if (i == 3)..(i == 15)
end

11
Doğru ... biri bunu bana açıklamak zorunda kalacak. Çalışıyor, ama nedenini anlayamıyorum.
Bob Aman

12
Flip flop operatörü bir durumdur. Onun devlet kısa zamanda gerçek geçer i == 3ve yanlış geçer sonra i != 3 ve i == 15. Bir flip-flop benzer: en.wikipedia.org/wiki/Flip-flop_%28electronics%29
Konstantin Haase

1
Buna tam olarak gizli bir özellik demezdim, çok fazla sıkıntı. İlk kez Freenode üzerinde #Ruby'de yıllar önce tanıtıldığımı hatırlıyorum; Temelde bu özellik dışında bir noktada Ruby'nin her özelliğini kullandım .
ELLIOTTCABLE

1
Buna can sıkıcı bir şey demem, sadece kullanmadığınız bir şey. Ben kullanmak ve özellikle bazı kriterlere göre dosyalardan satır blok kapma zaman kodu güzel azaltabilir.
Tin Man

49

Ruby ile ilgili harika şeylerden biri, yöntem veya sınıf tanımları gibi diğer dillerin kaşlarını çattığı yerlerde yöntemleri çağırabilir ve kod çalıştırabilmenizdir.

Örneğin, çalışma zamanına kadar bilinmeyen bir üst sınıfa sahip, yani rasgele olan bir sınıf oluşturmak için aşağıdakileri yapabilirsiniz:

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

end

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

Bu, 1.9 Array#sampleyöntemini kullanır (yalnızca 1.8.7'de, bkz. Array#choice) Ve örnek oldukça uyumludur, ancak gücü burada görebilirsiniz.

Bir başka harika örnek, sabit olmayan varsayılan parametre değerlerini koyma yeteneğidir (diğer diller genellikle talep ettiği gibi):

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

Tabii ki ilk örnekle ilgili problem, çağrı zamanına değil tanım zamanına göre değerlendirilmesidir. Böylece, bir üst sınıf seçildikten sonra, programın geri kalanı için bu üst sınıf kalır.

Bununla birlikte, ikinci örnekte, her aradığınızda do_something_at, atdeğişken yöntemin çağrıldığı zaman olacaktır (buna çok çok yakın)


2
Not: Dizi # rand, Rails dışında kullanabileceğiniz ActiveSupport tarafından sağlanırrequire 'activesupport'
rfunduk

Dizi # seçim 1.8.7'de
Josh Lee

24
Dizi # seçeneği yalnızca 1.8.7'dir ! Kullanmayın, 1.9'da gitti ve 1.8.8'de gidecek. #Sample
Marc-André Lafortune

python: class DictList ([dict, list] [random.randint (0,1)]): pass
Anurag Uniyal

def do_something_at (bir şey, at = lambda {Time.now}) at.call #now dinamik olarak zaman sonu ata
Jack Kinsella

47

Başka bir küçük özellik - a'yı Fixnum36'ya kadar herhangi bir tabana dönüştürün :

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

Huw Walters'ın yorumladığı gibi, diğer yolu dönüştürmek de basit:

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

1
Ve bütünlük için, String#to_s(base)bir tamsayıya dönüştürmek için kullanılabilir; "1001001100101100000001011010010".to_i(2), "499602d2".to_i(16)vb tüm orijinali iade Fixnum.
Huw Walters

40

Varsayılan değerlerle karmalar! Bu durumda bir dizi.

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

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

Metaprogramlamada çok faydalıdır.


1
Evet doğru. '=' İle zaten varsayılan değer atanmışsa (boş atama olsa bile umurumda değilse) Ruby karma '<<' operatörünü kabul edebilir, aksi takdirde karma '<<' kabul etmez. CMIIW
mhd

39

Ruby 1.9 kaynağını indirin ve sorun make golf, sonra böyle şeyler yapabilirsiniz:

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"

golf_prelude.cSaklanmak daha düzgün şeyler için okuyun .


38

1.9 Proc işlevselliğindeki bir diğer eğlenceli ek ise, Proc # curry olan ve Proc'u kabul eden bir Proc'u n-1'i kabul eden birine dönüştürmenizi sağlar. Burada yukarıda bahsettiğim Proc # === ipucu ile birleştirilmiştir:

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

35

Boole dışı değerlerde Boole işleçleri.

&& ve ||

Her ikisi de değerlendirilen son ifadenin değerini döndürür.

Bu nedenle ||=, değişken tanımlanmamışsa, değişkeni sağ tarafta döndürülen ifadeyle güncelleyecektir. Bu açıkça belgelenmiş değil, ortak bilgidir.

Ancak bu &&=pek yaygın olarak bilinmemektedir.

string &&= string + "suffix"

eşittir

if string
  string = string + "suffix"
end

Değişken tanımsızsa devam etmemesi gereken yıkıcı işlemler için çok kullanışlıdır.


2
Daha doğrusu, string &&= string + "suffix" eşdeğerdir string = string && string + "suffix". Bu &&ve ||ikinci argümanlarını geri döndürmek PickAx, s. 154 (Bölüm I - Yakut Yönleri, İfadeler, Koşullu Yürütme).
Richard Michael

29

Rails'in sağladığı Symbol # to_proc işlevi gerçekten harika.

Onun yerine

Employee.collect { |emp| emp.name }

Yazabilirsin:

Employee.collect(&:name)

Bu görünüşe göre, bir blok kullanmaktan daha "büyüklük sırası daha yavaştır". igvita.com/2008/07/08/6-optimization-tips-for-ruby-mri
Charles Roper

Sadece denedim ve ikisi arasında önemli bir fark olmadığını gördüm. Bu "büyüklük sırası" olayının nereden geldiğinden emin değilim. (Ruby 1.8.7'yi Kullanma)
Matt Grande

1
Bunu Rails dışında yapmak da kullanışlı ve require 'activesupport'aslında bu yardımcıların çoğunun bulunduğu yer.
rfunduk

8
bu, active_support'un uygulanması nedeniyle yavaştı, yani (1..10) .inject &: * gibi havalı boklar yapabilmeniz için birden fazla argümanı kabul etti, ancak ana kullanım durumu genellikle yalnızca bir toplama örn.% w (hızlı kahverengi tilki). harita &: upcase. 1.8.7'den itibaren çekirdek yakut ve performans makul.
Steve Graham

4
@ thenduks: Ve yakut 1.8.7 ve 1.9'da activesupport yardımı olmadan yapılabilir.
Andrew Grimm

28

Son bir tane - ruby'de dizeleri sınırlamak istediğiniz herhangi bir karakteri kullanabilirsiniz. Aşağıdaki kodu alın:

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

Dizenin içindeki çift tırnak işaretlerinden kaçmak istemiyorsanız, farklı bir sınırlayıcı kullanabilirsiniz:

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

Sınırlayıcılardan kaçmak zorunda kalmanın yanı sıra, bu sınırlayıcıları daha güzel çok satırlı dizeler için kullanabilirsiniz:

sql = %{
    SELECT strings 
    FROM complicated_table
    WHERE complicated_condition = '1'
}

19
herhangi bir karakter değil , ama yine de oldukça havalı. Diğer değişmez değerlerle de çalışır:% () /% {} /% [] /% <> /% || % r () /% r {} /% r [] /% r <> /% r || % w () /% w {} /% w [] /% w <> /% w ||
Bo Jeanes

Herenow doc sözdizimi de var: Ben vs. satırlı SQL ifadeleri gibi şeyler için kullanmak ister << BLOK ... BLOK,
Martin T.

26

Dinamik olarak oldukça ilginç ve iyi bilinmeyen yöntemler oluşturmak için define_method komutunu kullanarak buldum . Örneğin:

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

Yukarıdaki kod, "press1" ile "press9" arasındaki yöntemleri dinamik olarak oluşturmak için 'define_method' komutunu kullanır. Daha sonra, esas olarak aynı kodu içeren 10 yöntemin tümünü yazarken, bu yöntemleri gerektiğinde anında oluşturmak için define method komutu kullanılır.


4
Define_method ile ilgili tek sorun, blokların ruby ​​1.8'de parametre olarak geçirilmesine izin vermemesidir. Geçici çözüm için bu blog yayınına bakın .
Andrew Grimm


23

module_function

Module_function olarak bildirilen modül yöntemleri , Modülü içeren sınıfta kendilerinin özel kopya yöntemi olarak kopyalarını oluşturur :

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>

Module_function işlevini bağımsız değişken kullanmadan kullanırsanız , module_function deyiminden sonra gelen tüm modül yöntemleri otomatik olarak module_functions olur.

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!'

4
Modüllerdeki özel yöntemleri bildirmek istiyorsanız, özel anahtar kelimeyi kullanmanız yeterlidir. Modül içeren sınıflarda yöntemi özel yapmanın yanı sıra, module_function yöntemi modül örneğine kopyalar. Çoğu durumda bu istediğiniz şey değildir.
tomafro

Özel kullanabileceğinizi biliyorum. Ama bu Ruby'nin gizli özellikleri hakkında bir soru. Ve bence çoğu insan bunu doc'de görene ve onunla oynamaya başlayana kadar module_function (kendim dahil) duymadı.
newtonapple

module_function(2. yol) kullanmanın bir alternatifi sadece kullanmaktır extend self(ki bu oldukça hoş görünüyor: D)
J -_- L


21

Uyarı: Bu öğe 2008'in En Korkunç Hack # 1 oyu aldı , bu yüzden dikkatli kullanın. Aslında, veba gibi kaçının, ama kesinlikle Gizli Yakut.

Superators Ruby'ye Yeni Operatörler Ekliyor

Hiç kodunuzda benzersiz bir işlem için süper gizli bir el sıkışma operatörü istediniz mi? Kod golf oynamak gibi mi? - ~ + ~ - veya <--- gibi operatörleri deneyin. Bu sonuncusu bir öğenin sırasını tersine çevirmek için örneklerde kullanılır.

Ben bir ilgisi var Superators Projesi onu hayranlıkla ötesinde.


19

Partiye geç kaldım ama:

İki eşit uzunlukta diziyi kolayca alabilir ve anahtarları ve diğeri değerleri sağlayan bir dizi ile bunları bir karmaya dönüştürebilirsiniz:

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

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

(Bu, Dizi # zip'in iki dizideki değerleri "sıkıştırdığı" için çalışır:

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

Hash [] sadece böyle bir dizi alabilir. İnsanların da bunu yaptığını gördüm:

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

Hangisi aynı sonucu verir, ancak uyarma ve yassılaştırma tamamen gereksizdir - belki de geçmişte değildiler?)


3
Bu gerçekten uzun bir süre belgelenmemişti (bkz. Redmine.ruby-lang.org/issues/show/1385 ). Bu yeni formun Ruby 1.8.7
Marc-André Lafortune için 15

19

Ruby'deki karmaları otomatik yürütme

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 } } }

Bu çok kullanışlı olabilir.


1
Yerel hash init gibi aynı duyguya sahip olmak için bir modül içinde sarmak:module InfHash; def self.new; Hash.new {|h,k| h[k] = Hash.new(&h.default_proc)}; end; end
asaaki

16

Diziyi Yok Etme

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

Nerede:

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

Bu tekniği kullanarak, herhangi bir derinlikte iç içe diziden istediğimiz kesin değerleri elde etmek için basit atama kullanabiliriz.


15

Class.new()

Çalışma zamanında yeni bir sınıf oluşturun. Argüman, türetilecek bir sınıf olabilir ve blok sınıf gövdesidir. Ayrıca const_set/const_get/const_defined?, yeni sınıfınızı düzgün bir şekilde kaydettirmek için bakmak isteyebilirsiniz , böylece inspectsayı yerine bir ad yazdırılır.

Her gün ihtiyacınız olan bir şey değil, ama oldukça kullanışlı.


1
MyClass = Class.new Array do; def hi; 'hi'; end; endeşdeğer gibi görünüyor class MyClass < Array; def hi; 'hi'; end; end.
yfeldblum

1
Muhtemelen düşündüğümden daha doğrudur. Hatta sadece bir sabitten ziyade bir değişkenden miras alabileceğiniz görülüyor. Ancak, çalışma zamanında sınıf adını oluşturmanız gerekirse, şekerli sürüm (ikinci) işe yaramaz. (Baring eval, tabii ki.)
Justin Love

Bu teknik Metaprogramming Ruby kitabında oldukça iyi tanımlanmıştır .
Paul Pladijs

13

ardışık sayılar dizisi oluşturun:

x = [*0..5]

x'i [0, 1, 2, 3, 4, 5] olarak ayarlar


Evet, ama kısa ve tatlı değil;)
horseyguy

2
terslik nesneldir, okunabilirlik zevk ve deneyim meselesidir
Alexey

Splat ( *) operatörü temel olarak to_aher neyse çağırır .
Matheus Moreira

13

Rubyland'da gördüğünüz sihrin birçoğu, sizin için kod yazan bir kod yazan meta programlamayla ilgilidir. Ruby'nin attr_accessor, attr_readerve attr_writeronlar standart bir deseni izleyen bir çizgide iki yöntem oluşturmak ki, bütün basit metaprogramming vardır. Rails, has_oneve gibi ilişki yönetimi yöntemleriyle çok fazla meta programlama yapar belongs_to.

Ancak, class_evaldinamik olarak yazılmış kodu yürütmek için kendi meta programlı numaralarınızı oluşturmak oldukça basittir .

Aşağıdaki örnek, bir sarma nesnesinin belirli yöntemleri bir iç nesneye iletmesine izin verir:

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

Yöntem Wrapper.forwards, yöntemlerin adları için semboller alır ve bunları methodsdizide saklar . Ardından, verilenlerin her biri için define_method, işi tüm argümanlar ve bloklar dahil olmak üzere mesajı birlikte göndermek olan yeni bir yöntem oluşturmak için kullanırız .

Metaprogramlama sorunları için harika bir kaynak , Lucky Stiff'in "Metaprogramlamayı Açıkça Görmesi" nedenidir .


Önce yakutta meta programlamaya dalmak istiyorum. Başlamak için bazı referanslar verebilir misiniz (Verilen bağlantı dışında)? Kitaplar da yapacak. Teşekkürler.
Chirantan

PragProg'un video yayını serisi "Ruby Nesne Modeli ve Metaprogramlama", ruby ​​kullanarak meta programlamaya iyi bir giriş: pragprog.com/screencasts/v-dtrubyom/…
caffo

@Chirantan, bir göz metaprogramming Ruby .
Paul Pladijs

12

===(obj)vaka karşılaştırmaları için yanıt veren herhangi bir şey kullanın :

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(ve böylece Class) Regexp, Date(diğer) === ve tüm kullanılabilir: ve diğer birçok sınıfları bir örnek yöntemi tanımlar.

Ruby 1.9'daki gibi takma adın hatırlatıldığı için Farrel'e teşekkürler .Proc#callProc#===


11

"Yakut" ikili (en azından MRI) perl tek katmanlı oldukça popüler kılan bir çok anahtarı destekler.

Önemli olanlar:

  • -n Sadece "gets" ile bir dış döngü kurar - verilen dosya adı veya STDIN ile sihirli bir şekilde çalışır ve her okuma satırını $ _ olarak ayarlar.
  • -p -n'ye benzer, ancak puther döngü yinelemesinin sonunda otomatik s
  • -a $ F içinde saklanan her giriş satırında .split'e otomatik çağrı
  • -i Yerinde düzenleme giriş dosyaları
  • -l Girişte .chomp otomatik çağrısı
  • -e Bir parça kod yürütün
  • -c Kaynak kodunu kontrol edin
  • -w Uyarılarla

Bazı örnekler:

# 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

Tonlarca daha kullanışlı ve pratik örnekler için google "yakut tek gömlekleri" ve "perl tek gömlekleri" ni kullanmaktan çekinmeyin. Temel olarak ruby'yi awk ve sed için oldukça güçlü bir yedek olarak kullanmanıza izin verir.


10

Send () metodu Ruby herhangi Class veya Nesne üzerinde kullanılabilecek bir genel amaçlı bir yöntemdir. Geçersiz kılınmazsa, send () bir dizeyi kabul eder ve dizesini geçirilen yöntemin adını çağırır. Örneğin, kullanıcı “Clr” düğmesini tıklarsa, send () yöntemine 'press_clear' dizesi gönderilir ve 'press_clear' yöntemi çağrılır. Send () yöntemi, Ruby'deki işlevleri çağırmak için eğlenceli ve dinamik bir yol sağlar.

 %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

Bloglama Ayakkabıları: Basit Kireç Uygulaması'ndaki bu özellik hakkında daha fazla konuşuyorum


Bir güvenlik açığı açmak için harika bir yol gibi görünüyor.
mP.

4
Mümkün olan yerlerde sembolleri kullanırdım.
reto

9

Gerçekten gerektirmediği bir şey gerektirdiğini söyleyen bir sınıf veya modülü kandırın:

$" << "something"

Bu, örneğin A'nın B gerektirdiğinde, ancak kodumuzda B'ye ihtiyacımız olmadığında yararlıdır (ve A, kodumuz aracılığıyla da kullanmaz):

Örneğin, Backgroundrb'ler bdrb_test_helper requires 'test/spec', ancak hiç kullanmıyorsunuz, yani kodunuzda:

$" << "test/spec"
require File.join(File.dirname(__FILE__) + "/../bdrb_test_helper")

Bu, gem A'nın foo-1.0.0 ve gem B'nin foo-1.0.1 gerektirdiği sorunları çözüyor mu?
Andrew Grimm

Hayır. $ "gerektiren tarafından yüklenen modül adlarını içeren bir dizidir (modüllerin iki kez yüklenmesini önlemek için kullanılır). Bu nedenle, taşları kandırmak için kullanırsanız, taşlar gerçek" bir şeyi "kullanmaya çalıştığında çökme oluşturur Bunun yerine, en sonuncusu yerine bir geminin somut bir versiyonunu (ör. foo-1.0.0) zorla yerleştirmeyi zorlamak isteyebilirsiniz: docs.rubygems.org/read/chapter/4#page71
13.05.2018

9

Fixnum#to_s(base)bazı durumlarda gerçekten yararlı olabilir. Böyle bir durum rasgele sayıyı 36 tabanını kullanarak dizeye dönüştürerek rastgele (sözde) benzersiz belirteçler üretmektir.

Uzunluk uzunluğu belirteci:

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

Uzunluk uzunluğu belirteci:

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

9

Herhangi bir sayıda parametreyi kabul eden ve sadece hepsini atayan bir yöntem tanımlama

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

Yukarıdaki helloyöntemin sadece puts "hello"ekranda ve çağrıda olması gerekir super- ancak üst sınıf helloparametreleri tanımladığından - aslında parametrelerin kendisini kullanması gerekmediğinden - onlara bir ad vermek zorunda değildir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.