我喜欢ruby的一件事是,它主要是一种非常易读的语言(非常适合自我记录的代码)
然而,受到这个问题的启发:Ruby Code解释
并描述了如何||=在ruby中工作,我正在考虑我不使用的ruby习语,坦率地说,我并没有完全理解它们.
所以我的问题是,类似于引用问题的例子,我需要注意哪些常见但不明显的红宝石成语才能成为一名真正熟练的红宝石程序员?
顺便说一句,从引用的问题
a ||= b
Run Code Online (Sandbox Code Playgroud)
相当于
if a == nil || a == false
a = b
end
Run Code Online (Sandbox Code Playgroud)
(感谢Ian Terrell的更正)
编辑:事实证明,这一点并非完全没有争议.事实上正确的扩张
(a || (a = (b)))
Run Code Online (Sandbox Code Playgroud)
请参阅以下链接了解原因:
感谢JörgWMittag指出这一点.
ram*_*ion 50
允许相同文件作为库或脚本的magic if子句:
if __FILE__ == $0
# this library may be run as a standalone script
end
Run Code Online (Sandbox Code Playgroud)
包装和拆包阵列:
# put the first two words in a and b and the rest in arr
a,b,*arr = *%w{a dog was following me, but then he decided to chase bob}
# this holds for method definitions to
def catall(first, *rest)
rest.map { |word| first + word }
end
catall( 'franken', 'stein', 'berry', 'sense' ) #=> [ 'frankenstein', 'frankenberry', 'frankensense' ]
Run Code Online (Sandbox Code Playgroud)
哈希的合成糖作为方法论证
this(:is => :the, :same => :as)
this({:is => :the, :same => :as})
Run Code Online (Sandbox Code Playgroud)
哈希初始值设定项:
# this
animals = Hash.new { [] }
animals[:dogs] << :Scooby
animals[:dogs] << :Scrappy
animals[:dogs] << :DynoMutt
animals[:squirrels] << :Rocket
animals[:squirrels] << :Secret
animals #=> {}
# is not the same as this
animals = Hash.new { |_animals, type| _animals[type] = [] }
animals[:dogs] << :Scooby
animals[:dogs] << :Scrappy
animals[:dogs] << :DynoMutt
animals[:squirrels] << :Rocket
animals[:squirrels] << :Secret
animals #=> {:squirrels=>[:Rocket, :Secret], :dogs=>[:Scooby, :Scrappy, :DynoMutt]}
Run Code Online (Sandbox Code Playgroud)
元类语法
x = Array.new
y = Array.new
class << x
# this acts like a class definition, but only applies to x
def custom_method
:pow
end
end
x.custom_method #=> :pow
y.custom_method # raises NoMethodError
Run Code Online (Sandbox Code Playgroud)
类实例变量
class Ticket
@remaining = 3
def self.new
if @remaining > 0
@remaining -= 1
super
else
"IOU"
end
end
end
Ticket.new #=> Ticket
Ticket.new #=> Ticket
Ticket.new #=> Ticket
Ticket.new #=> "IOU"
Run Code Online (Sandbox Code Playgroud)
块,触发器和lambdas.生活和呼吸他们.
# know how to pack them into an object
block = lambda { |e| puts e }
# unpack them for a method
%w{ and then what? }.each(&block)
# create them as needed
%w{ I saw a ghost! }.each { |w| puts w.upcase }
# and from the method side, how to call them
def ok
yield :ok
end
# or pack them into a block to give to someone else
def ok_dokey_ok(&block)
ok(&block)
block[:dokey] # same as block.call(:dokey)
ok(&block)
end
# know where the parentheses go when a method takes arguments and a block.
%w{ a bunch of words }.inject(0) { |size,w| size + 1 } #=> 4
pusher = lambda { |array, word| array.unshift(word) }
%w{ eat more fish }.inject([], &pusher) #=> ['fish', 'more', 'eat' ]
Run Code Online (Sandbox Code Playgroud)
更多成语:
的使用%w,%r以及%(分隔符
%w{ An array of strings %}
%r{ ^http:// }
%{ I don't care if the string has 'single' or "double" strings }
Run Code Online (Sandbox Code Playgroud)
在case语句中键入比较
def something(x)
case x
when Array
# Do something with array
when String
# Do something with string
else
# You should really teach your objects how to 'quack', don't you?
end
end
Run Code Online (Sandbox Code Playgroud)
......并===在案件陈述中全面滥用该方法
case x
when 'something concrete' then ...
when SomeClass then ...
when /matches this/ then ...
when (10...20) then ...
when some_condition >= some_value then ...
else ...
end
Run Code Online (Sandbox Code Playgroud)
对于Rubyists来说应该是自然的东西,但对于来自其他语言的人来说可能并非如此:使用each赞成for .. in
some_iterable_object.each{|item| ... }
Run Code Online (Sandbox Code Playgroud)
在Ruby 1.9 +,Rails中,或通过修补Symbol#to_proc方法,这已成为一种越来越流行的习语:
strings.map(&:upcase)
Run Code Online (Sandbox Code Playgroud)
条件方法/常量定义
SOME_CONSTANT = "value" unless defined?(SOME_CONSTANT)
Run Code Online (Sandbox Code Playgroud)
查询方法和破坏性(爆炸)方法
def is_awesome?
# Return some state of the object, usually a boolean
end
def make_awesome!
# Modify the state of the object
end
Run Code Online (Sandbox Code Playgroud)
隐式splat参数
[[1, 2], [3, 4], [5, 6]].each{ |first, second| puts "(#{first}, #{second})" }
Run Code Online (Sandbox Code Playgroud)
我喜欢这个:
str = "Something evil this way comes!"
regexp = /(\w[aeiou])/
str[regexp, 1] # <- This
Run Code Online (Sandbox Code Playgroud)
哪个(大致)相当于:
str_match = str.match(regexp)
str_match[1] unless str_match.nil?
Run Code Online (Sandbox Code Playgroud)
或者至少那是我用来替换这些块的东西.
小智 7
我建议您阅读受到尊重和尊重的人群中流行且精心设计的插件或宝石的代码.
我遇到的一些例子:
if params[:controller] == 'discussions' or params[:controller] == 'account'
# do something here
end
Run Code Online (Sandbox Code Playgroud)
对应于
if ['account', 'discussions'].include? params[:controller]
# do something here
end
Run Code Online (Sandbox Code Playgroud)
以后会被重构
if ALLOWED_CONTROLLERS.include? params[:controller]
# do something here
end
Run Code Online (Sandbox Code Playgroud)
以下是一些从各种来源中挑选出来的:
使用"除非"和"直到"而不是"如果不是"和"而不是".但是,当存在"其他"条件时,尽量不要使用"除非".
请记住,您可以一次分配多个变量:
a,b,c = 1,2,3
Run Code Online (Sandbox Code Playgroud)
甚至没有临时交换变量:
a,b = b,a
Run Code Online (Sandbox Code Playgroud)
在适当的地方使用尾随条件,例如
do_something_interesting unless want_to_be_bored?
Run Code Online (Sandbox Code Playgroud)
要注意一个常用但不是很明显(至少对我来说)定义类方法的方法:
class Animal
class<<self
def class_method
puts "call me using Animal.class_method"
end
end
end
Run Code Online (Sandbox Code Playgroud)
一些参考:
顺便说一句,从引用的问题
Run Code Online (Sandbox Code Playgroud)a ||= b相当于
Run Code Online (Sandbox Code Playgroud)if a == nil a = b end
这是巧妙的错误,并且是新手Ruby应用程序中的错误来源.
由于两者(并且仅)nil和false评估为布尔值false,a ||= b实际上(几乎*)等效于:
if a == nil || a == false
a = b
end
Run Code Online (Sandbox Code Playgroud)
或者,用另一个Ruby习语重写它:
a = b unless a
Run Code Online (Sandbox Code Playgroud)
(*因为每个语句都有一个值,所以这些在技术上并不相同a ||= b.但是如果你不依赖于语句的值,你就不会看到差异.)