it-swarm-id.com

Fitur tersembunyi Ruby

Melanjutkan meme "Fitur tersembunyi ...", mari berbagi fitur yang kurang diketahui tetapi bermanfaat dari Ruby bahasa pemrograman.

Cobalah untuk membatasi diskusi ini dengan Ruby inti, tanpa Ruby pada Rails barang.

Lihat juga:

(Tolong, cukup satu fitur tersembunyi per jawaban.)

Terima kasih

160
squadette

Dari Ruby 1.9 Proc # === adalah alias untuk panggilan # Proc, yang berarti objek Proc dapat digunakan dalam pernyataan kasus seperti:

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
Farrel

Peter Cooper memiliki daftar yang baik dari Ruby trik. Mungkin favoritnya adalah memungkinkan item tunggal dan koleksi untuk disebutkan. (Yaitu, perlakukan non- koleksi objek sebagai koleksi yang berisi objek itu saja.) Kelihatannya seperti ini:

[*items].each do |item|
  # ...
end
76
James A. Rosen

Tidak tahu seberapa tersembunyi ini, tetapi saya merasa berguna ketika perlu membuat Hash dari array satu dimensi:

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

Hash[*fruit]    
=> {"Apple"=>"red", "banana"=>"yellow"}
64
astronautism

Satu trik yang saya suka adalah dengan menggunakan percikan (*) expander pada objek selain Array. Berikut ini contoh pada pencocokan ekspresi reguler:

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

Contoh lain termasuk:

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

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

Wow, tidak ada yang menyebut operator flip flop:

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

Salah satu hal keren tentang Ruby adalah Anda dapat memanggil metode dan menjalankan kode di tempat-tempat yang disukai oleh bahasa lain, seperti dalam definisi metode atau kelas.

Misalnya, untuk membuat kelas yang memiliki superclass yang tidak diketahui sampai waktu berjalan, yaitu acak, Anda bisa melakukan hal berikut:

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

end

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

Ini menggunakan 1.9 Array#sample metode (hanya dalam 1,8.7, lihat Array#choice), dan contohnya cukup dibuat tetapi Anda dapat melihat kekuatannya di sini.

Contoh keren lainnya adalah kemampuan untuk menempatkan nilai parameter default yang tidak tetap (seperti bahasa lain yang sering diminta):

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

Tentu saja masalah dengan contoh pertama adalah bahwa ia dievaluasi pada waktu definisi, bukan waktu panggilan. Jadi, sekali superclass telah dipilih, ia tetap superclass itu untuk sisa program.

Namun, dalam contoh kedua, setiap kali Anda menelepon do_something_at, variabel at akan menjadi waktu metode dipanggil (well, sangat sangat dekat dengannya)

49
Bo Jeanes

Fitur mungil lainnya - ubah Fixnum menjadi basis apa pun hingga 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"

Dan seperti komentar Huw Walters, mengonversi dengan cara lain sama mudahnya:

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

Hash dengan nilai default! Array dalam hal ini.

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

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

Sangat berguna dalam metaprogramming.

40
August Lilleaas

Unduh Ruby 1.9 sumber, dan terbitkan make golf, maka Anda dapat melakukan hal-hal seperti ini:

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"

Membaca golf_prelude.c untuk hal-hal yang lebih rapi bersembunyi.

39
manveru

Tambahan menyenangkan lainnya dalam fungsi 1.9 Proc adalah Proc # curry yang memungkinkan Anda untuk mengubah argumen yang menerima Proc menjadi argumen yang menerima n-1. Ini dia dikombinasikan dengan ujung Proc # === yang saya sebutkan di atas:

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
Farrel

Operator Boolean pada nilai non boolean.

&& dan ||

Keduanya mengembalikan nilai ekspresi terakhir yang dievaluasi.

Itulah sebabnya ||= akan memperbarui variabel dengan nilai yang dikembalikan ekspresi di sisi kanan jika variabel tidak terdefinisi. Ini tidak didokumentasikan secara eksplisit, tetapi pengetahuan umum.

Namun &&= tidak begitu banyak diketahui tentang.

string &&= string + "suffix"

setara dengan

if string
  string = string + "suffix"
end

Ini sangat berguna untuk operasi destruktif yang tidak boleh dilanjutkan jika variabel tidak terdefinisi.

35
EmFi

Fungsi Symbol # to_proc yang Rails sediakan benar-benar keren.

Dari pada

Employee.collect { |emp| emp.name }

Kamu bisa menulis:

Employee.collect(&:name)
29
hoyhoy

Satu yang terakhir - dalam Ruby Anda dapat menggunakan karakter apa pun yang ingin Anda batasi string. Ambil kode berikut:

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

Jika Anda tidak ingin lepas dari tanda kutip ganda dalam string, Anda bisa menggunakan pembatas yang berbeda:

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

Selain menghindari keharusan menghindari pembatas, Anda dapat menggunakan pembatas ini untuk string multiline yang lebih bagus:

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

Saya menemukan menggunakan perintah define_method untuk secara dinamis menghasilkan metode yang cukup menarik dan tidak terlalu dikenal. Sebagai contoh:

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

Kode di atas menggunakan perintah 'define_method' untuk secara dinamis membuat metode "press1" melalui "press9." Alih-alih mengetik semua 10 metode yang essentailly berisi kode yang sama, perintah metode define digunakan untuk menghasilkan metode ini dengan cepat sesuai kebutuhan.

26

Gunakan objek Range sebagai daftar malas tak terbatas:

Inf = 1.0 / 0

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

Info lebih lanjut di sini: http://banisterfiend.wordpress.com/2009/10/02/wtf-infinite-ranges-in-Ruby/

26
horseyguy

module_function

Metode-metode modul yang dideklarasikan sebagai module_function akan membuat salinan dirinya sebagai pribadi metode instance di kelas yang menyertakan Modul:

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>

Jika Anda menggunakan module_function tanpa argumen, maka metode modul apa pun yang muncul setelah pernyataan module_function akan secara otomatis menjadi fungsi module_functions sendiri.

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
newtonapple

Suntikan singkat, seperti:

Jumlah rentang:

(1..10).inject(:+)
=> 55
23
user130730

Peringatan: item ini terpilih sebagai # 1 Peretasan Paling Mengerikan 2008, jadi gunakan dengan hati-hati. Sebenarnya, hindarilah seperti wabah, tetapi yang paling pasti adalah Ruby Tersembunyi.

Superator Tambahkan Operator Baru ke Ruby

Pernah menginginkan operator jabat tangan super-rahasia untuk beberapa operasi unik dalam kode Anda? Suka bermain golf kode? Coba operator seperti - ~ + ~ - atau <--- Yang terakhir digunakan dalam contoh untuk membalik urutan item.

Saya tidak ada hubungannya dengan Proyek Superators di luar mengaguminya.

21
Captain Hammer

Saya terlambat ke pesta, tetapi:

Anda dapat dengan mudah mengambil dua array dengan panjang yang sama dan mengubahnya menjadi hash dengan satu array memasok kunci dan yang lainnya nilainya:

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

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

(Ini berfungsi karena Array # Zip "zip" nilai-nilai dari dua array:

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

Dan Hash [] dapat mengambil array seperti itu. Saya telah melihat orang melakukan ini juga:

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

Yang menghasilkan hasil yang sama, tetapi percikan dan ratakan sama sekali tidak perlu - mungkin mereka tidak di masa lalu?)

19
Jordan Running

hash vivifying otomatis di 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 } } }

Ini bisa sangat berguna.

19
Trevoke

Menghancurkan Array

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

Dimana:

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

Dengan menggunakan teknik ini kita dapat menggunakan penugasan sederhana untuk mendapatkan nilai tepat yang kita inginkan dari array bersarang dari kedalaman apa pun.

16
horseyguy

Class.new()

Buat kelas baru saat run time. Argumennya bisa berupa kelas untuk diturunkan, dan bloknya adalah badan kelas. Anda mungkin juga ingin melihat const_set/const_get/const_defined? untuk mendaftarkan kelas baru Anda dengan benar, sehingga inspect mencetak nama alih-alih nomor.

Bukan sesuatu yang Anda butuhkan setiap hari, tetapi cukup berguna saat Anda melakukannya.

15
Justin Love

buat array angka berurutan:

x = [*0..5]

set x ke [0, 1, 2, 3, 4, 5]

13
horseyguy

Banyak keajaiban yang Anda lihat di Rubyland ada hubungannya dengan metaprogramming, yang hanya menulis kode yang menulis kode untuk Anda. Ruby attr_accessor, attr_reader, dan attr_writer semuanya metaprogramming sederhana, karena mereka membuat dua metode dalam satu baris, mengikuti pola standar. Rails melakukan banyak metaprogramming dengan metode manajemen hubungan mereka seperti has_one dan belongs_to.

Tapi cukup mudah untuk membuat trik metaprogramming Anda sendiri menggunakan class_eval untuk mengeksekusi kode yang ditulis secara dinamis.

Contoh berikut memungkinkan objek pembungkus untuk meneruskan metode tertentu ke objek internal:

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

Metode Wrapper.forwards mengambil simbol untuk nama metode dan menyimpannya dalam array methods. Kemudian, untuk masing-masing yang diberikan, kami menggunakan define_method untuk membuat metode baru yang tugasnya mengirim pesan, termasuk semua argumen dan blok.

Sumber yang bagus untuk masalah metaprogramming adalah Mengapa Lucky Stiff's "Seeing Metaprogramming Clearly" .

13
TALlama

gunakan apa pun yang merespons ===(obj) untuk perbandingan kasus:

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 (dan dengan demikian Class), Regexp, Date, dan banyak kelas lainnya mendefinisikan metode instance: === (lainnya), dan dapat semuanya digunakan.

Terima kasih kepada Farrel untuk pengingat Proc#call alias atau Proc#=== dalam Ruby 1.9.

12
James A. Rosen

Biner "Ruby" (setidaknya MRI) mendukung banyak sakelar yang menjadikan Perl one-liner cukup populer.

Yang signifikan:

  • -n Mengatur loop luar hanya dengan "mendapat" - yang secara ajaib bekerja dengan nama file atau STDIN yang diberikan, mengatur setiap baris baca dalam $ _
  • -p Mirip dengan -n tetapi dengan puts otomatis di akhir setiap iterasi loop
  • -a Panggilan otomatis ke .split pada setiap jalur input, disimpan dalam $ F
  • -i Di tempat mengedit file input
  • -l Panggilan otomatis ke .chomp on input
  • -E Menjalankan sepotong kode
  • -c Periksa kode sumber
  • -w Dengan peringatan

Beberapa contoh:

# 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

Jangan ragu untuk google "Ruby one-liners" dan "Perl one-liners" untuk banyak contoh yang lebih berguna dan praktis. Ini pada dasarnya memungkinkan Anda untuk menggunakan Ruby sebagai pengganti yang cukup kuat untuk awk dan sed.

11
minaguib

Metode send () adalah metode tujuan umum yang dapat digunakan pada Kelas atau Objek apa pun di Ruby. Jika tidak diganti, kirim () menerima string dan memanggil nama metode yang stringnya dilewatkan. Misalnya, jika pengguna mengklik tombol “Clr”, string ‘press_clear’ akan dikirim ke metode send () dan metode ‘press_clear’ akan dipanggil. Metode send () memungkinkan cara yang menyenangkan dan dinamis untuk memanggil fungsi di 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

Saya berbicara lebih banyak tentang fitur ini di Blogging Shoes: The Simple-Calc Application

10
private unless Rails.env == 'test'
# e.g. a bundle of methods you want to test directly

Sepertinya keren dan (dalam beberapa kasus) Bagus/berguna hack/fitur Ruby.

9
Szymon Jeż

Fixnum#to_s(base) dapat sangat berguna dalam beberapa kasus. Salah satu kasus tersebut adalah menghasilkan token acak (pseudo) unik dengan mengonversi angka acak menjadi string menggunakan basis 36.

Token dengan panjang 8:

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

Token dengan panjang 6:

Rand(36**6).to_s(36) => "bvhl8d"
Rand(36**6).to_s(36) => "lb7tis"
Rand(36**6).to_s(36) => "ibwgeh"
9
sickill

Menipu beberapa kelas atau modul yang mengatakan itu membutuhkan sesuatu yang sebenarnya tidak diperlukan:

$" << "something"

Ini berguna misalnya ketika membutuhkan A yang pada gilirannya membutuhkan B tetapi kami tidak membutuhkan B dalam kode kami (dan A tidak akan menggunakannya baik melalui kode kami):

Misalnya, Backgroundrb bdrb_test_helper requires'test/spec', tetapi Anda tidak menggunakannya sama sekali, jadi dalam kode Anda:

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

Mendefinisikan metode yang menerima sejumlah parameter dan hanya membuang semuanya

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

Metode hello di atas hanya perlu puts"hello" di layar dan panggil super - tetapi karena superclass hello mendefinisikan parameter yang harusnya juga - namun karena ia tidak benar-benar perlu menggunakan parameter itu sendiri - ia tidak harus memberi mereka nama.

9
horseyguy

Untuk menggabungkan beberapa regex dengan |, Anda dapat gunakan

Regexp.union /Ruby\d/, /test/i, "cheat"

untuk membuat Regexp mirip dengan:

/(Ruby\d|[tT][eE][sS][tT]|cheat)/
8
J-_-L

Saya menemukan ini berguna dalam beberapa skrip. Itu memungkinkan untuk menggunakan variabel lingkungan secara langsung, seperti dalam skrip Shell dan Makefiles. Variabel lingkungan digunakan sebagai cadangan untuk konstanta Ruby yang tidak terdefinisi.

>> class <<Object
>>  alias :old_const_missing :const_missing
>>  def const_missing(sym)
>>   ENV[sym.to_s] || old_const_missing(sym)
>>  end
>> end
=> nil

>> puts Shell
/bin/zsh
=> nil
>> TERM == 'xterm'
=> true
8
Ropez

Bagaimana dengan membuka file berdasarkan ARGV [0]?

readfile.rb:

$<.each_line{|l| puts l}

Ruby readfile.rb testfile.txt

Ini cara pintas yang bagus untuk menulis skrip satu kali. Ada banyak variabel yang tidak ditentukan yang sebagian besar orang tidak ketahui. Gunakan dengan bijak (baca: jangan membuang basis kode yang Anda rencanakan untuk mempertahankannya, itu bisa berantakan).

8
Scott Holden

Saya penggemar:

%w{An Array of strings} #=> ["An", "Array", "of", "Strings"]

Agak lucu seberapa sering itu berguna.

5
Judson

Nilai pengembalian berganda

def getCostAndMpg
    cost = 30000  # some fancy db calls go here
    mpg = 30
    return cost,mpg
end
AltimaCost, AltimaMpg = getCostAndMpg
puts "AltimaCost = #{AltimaCost}, AltimaMpg = #{AltimaMpg}"

Penugasan Paralel

i = 0
j = 1
puts "i = #{i}, j=#{j}"
i,j = j,i
puts "i = #{i}, j=#{j}"

Atribut Virtual

class Employee < Person
  def initialize(fname, lname, position)
    super(fname,lname)
    @position = position
  end
  def to_s
     super + ", #@position"
  end
  attr_writer :position
  def etype
     if @position == "CEO" || @position == "CFO"
         "executive"
     else
         "staff"
     end
  end
end
employee = Employee.new("Augustus","Bondi","CFO")
employee.position = "CEO"
puts employee.etype    =>  executive
employee.position = "Engineer"
puts employee.etype    =>  staff

method_missing - ide bagus

(Dalam sebagian besar bahasa ketika suatu metode tidak dapat ditemukan dan kesalahan dilemparkan dan program Anda berhenti. Dalam Ruby Anda sebenarnya dapat menangkap kesalahan itu dan mungkin melakukan sesuatu yang cerdas dengan situasi tersebut)

class MathWiz
  def add(a,b) 
    return a+b
  end
  def method_missing(name, *args)
    puts "I don't know the method #{name}"
  end
end
mathwiz = MathWiz.new
puts mathwiz.add(1,4)
puts mathwiz.subtract(4,2)

5

Saya tidak tahu metode kurangi

nol

5
Ramiz Uddin

Tip James A. Rosen keren ([* item]. Setiap), tetapi saya menemukan bahwa itu menghancurkan hash:

irb(main):001:0> h = {:name => "Bob"}
=> {:name=>"Bob"}
irb(main):002:0> [*h]
=> [[:name, "Bob"]]

Saya lebih suka cara menangani kasing ini ketika saya menerima daftar hal-hal untuk diproses tetapi saya menerima dan memungkinkan penelepon untuk memasok satu:

irb(main):003:0> h = {:name => "Bob"}
=> {:name=>"Bob"}
irb(main):004:0> [h].flatten
=> [{:name=>"Bob"}]

Ini dapat dikombinasikan dengan metode tanda tangan seperti dengan sangat baik:

def process(*entries)
  [entries].flatten.each do |e|
    # do something with e
  end
end
4
minaguib

Saya hanya suka kata kunci sebaris penyelamatan seperti ini:
CONTOH EDITED:

@user #=> nil (but I did't know)
@user.name rescue "Unknown"
link_to( d.user.name, url_user( d.user.id, d.user.name)) rescue 'Account removed'

Ini menghindari melanggar Aplikasi saya dan jauh lebih baik daripada fitur yang dirilis di Rails . Try ()

4
Fabiano Soriani

Memanggil metode yang didefinisikan di mana saja dalam rantai pewarisan, meskipun diganti

Objek ActiveSupport terkadang menyamar sebagai objek bawaan.

 memerlukan 'active_support' 
 hari = 5.days 
 days.class # => Fixnum 
 days.is_a? (Fixnum) # (> Fixnum) # => true 
 Fixnum === hari # => false (hah? Apa kamu sebenarnya?) 
 Object.instance_method (: class) .bind (days) .call # => ActiveSupport :: Durasi (aha!) 
 ActiveSupport :: Durasi === hari # => true 

Di atas, tentu saja, bergantung pada kenyataan bahwa active_support tidak mendefinisikan kembali Object # instance_method, dalam hal ini kita benar-benar akan menjadi sungai. Kemudian lagi, kita selalu bisa menyimpan nilai pengembalian Object.instance_method (: class) sebelum pustaka pihak ketiga mana pun dimuat.

Object.instance_method (...) mengembalikan UnboundMethod yang kemudian Anda dapat ikat ke instance kelas itu. Dalam hal ini, Anda dapat mengikatnya ke instance Object (termasuk subclass).

Jika kelas objek menyertakan modul, Anda juga dapat menggunakan UnboundMethod dari modul tersebut.

 modul Mod 
 def var_add (selengkapnya); @ var + lebih banyak; end 
 end 
 kelas Cla 
 termasuk Mod 
 def menginisialisasi (var); @ var = var; end 
 # override 
 def var_add (selengkapnya); @ var + lebih + lebih; end 
 end 
 cla = Cla.new ('abcdef') 
 cla.var_add ('ghi') # => "abcdefghighi" 
 Mod.instance_method ( : var_add) .bind (cla) .call ('ghi') # => "abcdefghi" 

Ini bahkan berfungsi untuk metode singleton yang menimpa metode instance kelas milik objek.

 kelas Foo 
 def mymethod; 'asli'; end 
 end 
 foo = Foo.new 
 foo.mymethod # => 'asli' 
 def foo.mymethod; 'singleton'; end 
 foo.mymethod # => 'singleton' 
 Foo.instance_method (: mymethod) .bind (foo) .call # => 'original' 
 
 # Anda juga dapat memanggil metode #instance di kelas singleton: 
 Kelas << foo; diri; end.instance_method (: mymethod) .bind (foo) .call # => 'singleton' 
4
Kelvin

Ada beberapa aspek simbol literal yang harus diketahui orang. Satu kasus yang diselesaikan oleh literal simbol khusus adalah ketika Anda perlu membuat simbol yang namanya menyebabkan kesalahan sintaksis karena suatu alasan dengan sintaks literal simbol simbol normal:

:'class'

Anda juga dapat melakukan interpolasi simbol. Dalam konteks accessor, misalnya:

define_method :"#{name}=" do |value|
  instance_variable_set :"@#{name}", value
end
3
Tom

each_with_index metode untuk objek enumarable (array, hash, dll.) mungkin?

myarray = ["la", "li", "lu"]
myarray.each_with_index{|v,idx| puts "#{idx} -> #{v}"}

#result:
#0 -> la
#1 -> li
#2 -> lu

Mungkin lebih dikenal daripada jawaban lain tetapi tidak terlalu terkenal untuk semua Ruby programmer :)

3
mhd
class A

  private

  def my_private_method
    puts 'private method called'
  end
end

a = A.new
a.my_private_method # Raises exception saying private method was called
a.send :my_private_method # Calls my_private_method and prints private method called'
2
Chirantan

Ruby memiliki mekanisme call/cc yang memungkinkan seseorang untuk secara bebas naik turun tumpukan.

Contoh sederhana berikut. Ini tentu saja bukan bagaimana seseorang akan mengalikan urutan dalam Ruby, tetapi ini menunjukkan bagaimana seseorang dapat menggunakan panggilan/cc untuk mencapai tumpukan untuk membuat hubungan pendek suatu algoritma. Dalam hal ini, kami secara berulang mengalikan daftar angka sampai kami melihat setiap angka atau kami melihat nol (dua kasus di mana kami tahu jawabannya). Dalam kasus nol, kita dapat secara sewenang-wenang berada jauh di dalam daftar dan mengakhiri.

#!/usr/bin/env Ruby

def rprod(k, rv, current, *nums)
  puts "#{rv} * #{current}"
  k.call(0) if current == 0 || rv == 0
  nums.empty? ? (rv * current) : rprod(k, rv * current, *nums)
end

def prod(first, *rest)
  callcc { |k| rprod(k, first, *rest) }
end

puts "Seq 1:  #{prod(1, 2, 3, 4, 5, 6)}"
puts ""
puts "Seq 2:  #{prod(1, 2, 0, 3, 4, 5, 6)}"

Anda dapat melihat hasilnya di sini:

http://codepad.org/Oh8ddh9e

Untuk contoh yang lebih kompleks dengan menampilkan kelanjutan yang bergerak ke arah lain pada stack, baca sumbernya ke Generator .

2
Dustin

Saya baru saja membaca semua jawaban ... satu kekurangan penting adalah menghancurkan tugas:

> (a,b),c = [[1,2],3]
=> [[1,2],3]
> a
=> 1

Ini juga berfungsi untuk parameter blok. Ini berguna ketika Anda memiliki array bersarang, masing-masing elemen mewakili sesuatu yang berbeda. Alih-alih menulis kode seperti "array [0] [1]", Anda dapat memecah array bersarang itu dan memberikan nama deskriptif untuk setiap elemen, dalam satu baris kode.

2
Alex D
@user #=> nil (but I did't know)
@user.name rescue "Unknown"
2
haoqi

Pintasan sprintf

Favorit saya Ruby. Sintaksnya adalah format_string % argument

"%04d"  % 1         # => "0001"
"%0.2f" % Math::PI  # => "3.14"

Berfungsi juga untuk array (format_string % array_of_arguments)

"%.2f %.3f %.4f" % ([Math::PI]*3) 
# => "3.14 3.142 3.1416"
1
iblue