Struct
, Comparable
, Marshal
, IO
& File
, RubyVM::InstructionSequence
OpenStruct
Посочвате зависимостите на вашия проект във файл, наречен `Gemfile`
source 'https://rubygems.org'
gem 'rails'
gem 'rubocop'
gem 'rspec'
Пускате командата bundle install
и сте готови. Bundler ще се погрижи за останалото.
bundle init
- генерира Gemfile в текущата директория
bundle install
- инсталира зависимостите, посочени в Gemfile
-a
bundle update
- обновява зависимостите до последните им версии
bundle exec
- изпълнява команда в контекста на правилните версии на посочените зависимостиМоже да уточнявате каква версия на библиотека да се използва:
gem 'rspec', '3.5'
gem 'rspec', '>=3.5'
gem 'rspec', '~> 3.5'
~>
!?
gem 'library', '>= 2.2.0'
- "optimistic" version constraint
gem 'library', '~> 2.2'
- "pessimistic" version constraint
>= 2.2.0
означава "всичко от тази версия нагоре е ок"
~> 2.0.3
е еквивалентно на >= 2.0.3 и < 2.1
~> 2.1
е еквивалентно на >= 2.1 и < 3.0
~> 0
е еквивалентно на >= 0.0 и < 1.0
bundle exec <команда> <аргумент1> <аргумент2> ...
bundle exec rails server
bundle exec rspec
Обещахме ви Sinatra пример с повече детайли
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>
Struct vs Class
Struct vs Hash
<=>
и правите 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