require
.
В Ruby код от други файлове се импортира с require
.
Например:
require 'bigdecimal'
require 'bigdecimal/util'
require 'foo'
търси файл foo.rb
в "пътят за зареждане".
require 'foo/bar'
търси директория foo
с файл bar.rb
.
require './foo'
търси foo.rb
в текущата директория.
require '/home/skanev/foo.rb'
.$LOAD_PATH
.$:
$:.unshift(path)
require
-а. Почти.
main
обекта е същия.
require
-и не правят нищо.
require
може да зарежда .so
и .dll
файлове.. ├── README.rdoc ├── Rakefile ├── bin │ └── skeptic ├── features ├── lib │ ├── skeptic │ │ ├── rules.rb │ │ └── scope.rb │ └── skeptic.rb ├── skeptic.gemspec └── spec
lib/
обикновено съдържа foo.rb
и lib/foo/
.
foo.rb
обикновено е единственото нещо в lib/
.
lib/foo
.
lib/
се добавя в load path.
require 'foo'
или require 'foo/something'
.
require
областта.
require
и $LOAD_PATH
и вижте какво се случва.load
е много сходен с require
, но има няколко разлики.
load 'foo.rb'
.
load
-ове изпълняват файла.
load
не може да зарежда .so
/.dll
библиотеки.
load
има опционален параметър, с който може да обвие файла в анонимен модул.
Ред малки, дребни, забавни неща в Ruby.
#eql?
прави сравнение без type coercion.1 == 1.0 # true
1.eql?(1.0) # false
$!
е последното "възбудено" изключение$@
е stacktrace-а на последното изключениеТялото на функция може да работи като begin/end
.
def foo
begin
get_a_life
ensure
puts 'rm -rf ~/.history'
end
end
def bar
get_a_life
ensure
puts 'rm -rf ~/.history'
end
Едно от любимите ми неща в Ruby.
retry
изпълнява begin
блока отначало.
retries_left = 3
begin
connect_to_facebook
rescue ConnectionError
retries_left -= 1
retry if retries_left > 0
end
Има много хубава семантика за тях.
излизане от... | рестартиране на... | |
---|---|---|
...блока | next | redo |
...метода | break | retry |
За нещастие, retry
не работи извън rescue
от Ruby 1.9 насам.
Има по-кратък начин за дефиниране на класови методи:
class Person
def Person.count
42
end
def self.count
42
end
end
Второто е по-криптично, по пък е по-DRY.
class Person
@@count = 0
def initialize
@@count += 1
end
def self.how_many
@@count
end
end
Person.new
Person.new
Person.how_many # 2
@@
.
NameError
(за разлика от @).
class B
@@foo = 1
def self.foo() @@foo end
def self.hmm() @@bar end
end
class D < B
@@bar = 2
def self.bar() @@bar end
def self.change() @@foo = 3; @@bar = 4; end
end
[B.foo, D.foo, D.bar] # [1, 1, 2]
B.hmm # error: NameError
D.change
[B.foo, D.foo, D.bar] # [3, 3, 4]
B.hmm # error: NameError
D.hmm # error: NameError
Object#send
изпраща някакво съобщение на метод.
numbers = [1, 2, 3, 4, 5, 6]
numbers.inject(0) { |a, b| a + b } # 21
numbers.send(:inject, 0) { |a, b| a + b } # 21
send
вика private методи.public_send
, който избягва да вика private
методи.method_missing
.
Object
и хвърля NoMethodError
.
super
.
class Hash
def method_missing(name, *args, &block)
args.empty? ? self[name] : super
end
end
things = {fish: 'Nemo', lion: 'Simba'}
things.fish # "Nemo"
things.lion # "Simba"
things.larodi # nil
things.foo(1) # error: NoMethodError
Има и коварни моменти:
class Hash
def method_missing(name, *arg, &block)
args.empty? ? self[name] : super
end
end
things = {lion: 'Simba'}
things.lion# ~> -:3: stack level too deep (SystemStackError)
arg
вместо args
.
args
всъщност е self.args
.
a = "hello there"
a[1] #=> "e"
a[1,3] #=> "ell"
a[1..3] #=> "ell"
a[-3,2] #=> "er"
a[-4..-2] #=> "her"
a[12..-1] #=> nil
a[-2..-4] #=> ""
a[/[aeiou](.)\1/] #=> "ell"
a[/[aeiou](.)\1/, 0] #=> "ell"
a[/[aeiou](.)\1/, 1] #=> "l"
a[/[aeiou](.)\1/, 2] #=> nil
a["lo"] #=> "lo"
a["bye"] #=> nil
Всъщност, #initialize
е просто instance метод.
Class#new
е имплементиран горе-долу така:
class Class
def new
object = self.allocate
object.send :initialize
object
end
end
module Unicode
def self.const_missing(name)
if name.to_s =~ /^U([0-9a-fA-F]{4,5}|10[0-9a-fA-F]{4})$/
codepoint = $1.to_i(16)
utf8 = [codepoint].pack('U')
utf8.freeze
const_set(name, utf8)
utf8
else
super
end
end
end
Unicode::U20AC # "\u20AC"
Unicode::U221E # "\u221E"
Unicode::Baba # error: NameError
#dup
и #clone
правят копие на обект.
#initialize_copy
.
#clone
копира singleton методи и freeze-ва обекта, ако е замразен. Така по-ясно ли е?