Struct
, Comparable
, Marshal
, IO
& File
RubyVM::InstructionSequence
OpenStruct
Ще продължим с Ruby core & stdlib.
core
; сега ще видим още няколко интересни класаStruct
Виждате, че може да добавите и свои методи там
Customer = Struct.new(:name, :address) do
def greeting
"Hello #{name}!"
end
end
dave = Customer.new('Dave', '123 Main')
dave.name # => "Dave"
dave.address # => "123 Main"
dave.greeting # => "Hello Dave!"
Обектите от тип Struct
приличат на колекции (хешове):
Customer = Struct.new(:name, :address, :zip)
john = Customer.new('John Doe', '123 Maple, Anytown NC', 12345)
john.name # => "John Doe"
john['name'] # => "John Doe"
john[:name] # => "John Doe"
john[0] # => "John Doe"
john.length # => 3
john.each # => #<Enumerator: #<struct Customer name="John Doe", address="123 Maple, Anytown NC", zip=12345>:each>
Удобно е да се ползва в тестове. За production код – по-рядко.
<=>
и правите include Comparable
<
, <=
, ==
, >=
, >
и between?
class Money
include Comparable
attr :amount, :currency
def initialize(amount, currency)
@amount, @currency = amount, currency
end
def <=>(money)
return unless currency == money.currency
amount <=> money.amount
end
end
Money.new(15, :BGN) < Money.new(30, :BGN) # => true
Marshal.load
и Marshal.dump
marshal_dump
и marshal_load
data = [42, :answer, {foo: 'bar'}]
serizlized = Marshal.dump data
serizlized # => "\x04\b[\bi/:\vanswer{\x06:\bfooI\"\bbar\x06:\x06ET"
Marshal.load(serizlized) == data # => true
Marshal.load(serizlized) # => [42, :answer, {:foo=>"bar"}]
Marshal
може да се ползва YAML
, от стандартната библиотека
Прочитане на цял файл като низ:
File.read('/etc/resolv.conf') # => "The contents of the file as a string."
Отваряне на файл, работа с обекта и автоматично затваряне на файла при излизане от блока:
File.open('foo/bar.txt', 'w') do |file|
file.write 'Some data.'
file.puts 'Some other data, with a newline at the end.'
file.puts 'File will be closed automatically, even in case of an exception in the block.'
end
code = 'puts ["a" * 10].first'
compiled = RubyVM::InstructionSequence.compile(code)
puts compiled.disasm
Резултат:
== disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>========== 0000 trace 1 ( 1) 0002 putself 0003 putstring "a" 0005 putobject 10 0007 opt_mult <callinfo!mid:*, argc:1, ARGS_SKIP> 0009 newarray 1 0011 opt_send_simple <callinfo!mid:first, argc:0, ARGS_SKIP> 0013 opt_send_simple <callinfo!mid:puts, argc:1, FCALL|ARGS_SKIP> 0015 leave
puts RubyVM::InstructionSequence.compile('a, b = 1, 2').disasm
Можем да видим, че a, b = 1, 2
минава през създаване на един обект тип Array
:
== disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>========== local table (size: 3, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, keyword: 0@4] s1) [ 3] a [ 2] b 0000 trace 1 ( 1) 0002 duparray [1, 2] 0004 dup 0005 expandarray 2, 0 0008 setlocal_OP__WC__0 3 0010 setlocal_OP__WC__0 2 0012 leave
require 'somelib'
, например require 'bigdecimal'
abbrev base64 benchmark bigdecimal cgi cmath coverage csv curses date dbm debug delegate digest dl drb e2mmap English erb etc extmk fcntl fiddle fileutils find forwardable gdbm getoptlong gserver io/console io/nonblock io/wait ipaddr irb json logger mathn matrix minitest minitest/benchmark minitest/spec mkmf monitor mutex_m net/ftp net/http net/imap net/pop net/smtp net/telnet nkf objspace observer open-uri open3 openssl optparse ostruct pathname pp prettyprint prime profile profiler pstore psych pty racc racc/parser rake rdoc readline resolv resolv-replace rexml rinda ripper rss rubygems scanf sdbm securerandom set shell shellwords singleton socket stringio strscan sync syslog tempfile test/unit thread thwait time timeout tk tmpdir tracer tsort un uri weakref webrick win32ole xmlrpc yaml zlib
OpenStruct
require 'ostruct'
marshal_load
и marshal_dump
, може да видите как за пример
Hash
, като each_pair
и методите []
и []=
require 'ostruct'
john = OpenStruct.new
john.name = 'John Doe'
john.age = 33
john.name # => "John Doe"
john.age # => 33
john.address # => nil
Долното е извадка от GNU GPL лиценза за отворен код:
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
Долното е извадка от GNU GPL лиценза за отворен код:
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
Ние, програмистите, не вярваме на собствения си код, та какво остава за чуждия такъв?
Така и трябва. Колкото по-малко зависимости от чужд (third-party) код – толкова по-добре.
Изобщо, колкото по-малко код, откъдето и да е дошъл – толкова по-добре. Но това е друга тема.
От друга страна, не може да си напишем всичко. Трябва да стъпим на нещо. И трябва да знаем как да изберем на какво.
Като изключим "помощни" gem-ове, най-популярният е Rails (с десетки милиони изтегляния)
rubygems.org/gems/именабиблиотеката
→ линк "Source code" или "Homepage"
gem install gemname --platform=ruby
https://github.com/rails/rails/tree/master/activesupport
https://github.com/rails/rails/tree/master/activerecord
mysql2
, pg
, sqlite3
и т.н.
https://github.com/ruby/curses
https://github.com/capistrano/capistrano
Deploy WordPress with Capistrano!
https://github.com/bundler/bundler или http://bundler.io
Практически задължително за всеки проект, който има нужда от други gem-ове.
%
на String
е много удобен за интерполация и форматиране на определени низове
Kernel.sprintf
%
може да се ползва и без точка, като други методи, наподобяващи операториКогато имаме повече от една стойност за интерполация, трябва да подадем списък:
'%02d' % 7 # => "07"
'%02d:%02d:%02d' % [19, 5, 2] # => "19:05:02"
name = 'Пешо'
'Здравей, <strong>%s</strong>!' % name # => "Здравей, <strong>Пешо</strong>!"
template = '
<html>
<head>
<title>%{title}</title>
</head>
<body>
%{content}
</body>
</html>
'
variables = {
title: 'String Interpolation',
content: 'Made easy by Kernel.sprintf.',
foobar: 'Extra keys are not an issue.'
}
template % variables # => "\n <html>\n <head>\n <title>String Interpolation</title>\n </head>\n <body>\n Made easy by Kernel.sprintf.\n </body>\n </html>\n"