ruby程式語言入門導覽
TRANSCRIPT
PowerPoint Presentation
RUBY
[email protected] 2010.05.23@ OSSF
Who am I?
Ryudo
http://blog.freebbs.tw
twitter: ryudoawaru
2007Ruby(Rails)
TOMLAN Software Studio founder
http://www.freebbs.tw
http://www.gameclub.tw
http://ryudo.freebbs.tw/
Ruby?
(interpreted)(script)
Yukihiro Matsumoto
Lisp, Perl, Smalltalk
irb: Interactive Ruby
ryudo@ryudo-x61:~$ irbirb(main):001:0> 1+3=> 4irb(main):002:0> 'hello' + ' world'=> "hello world"
IRB(Interactive Ruby Shell)
Ruby
Ruby/PHP/Perl/Python/VB
Java/C/C++
Ruby/JAVA
PHP
Ruby(Strongly typed)
irb(main):003:0> i=1=> 1irb(main):004:0> 'hello' + i
TypeError: can't convert Fixnum into String from (irb):4:in `+' from (irb):4
Integer
1051000099999999999999999999990-100000
Float
1.1-100.283.14159
PUTS.to_s
P.inspect
debug
getsenter
.chomp
()
1+1 #= 2200*3 #= 600 10-999 #= -989 100/20 #= 5 100/30 #= 3
(Float)
irb(main):001:0> 5 * 2.0 => 10.0 irb(main):002:0> 2.0 + 100.2 => 102.2 irb(main):003:0> 2.2 * 5.5 => 12.1 irb(main):004:0> 100.0 / 4.0 => 25.0 irb(main):008:0> 9.0 / 2.0 => 4.5
puts 5 * (10 + 5) -13 puts 999 + (31456 / (13 * 7) ) * -70
String
puts 'Hello, world!' puts '' puts 'Good-bye.'
puts ''
Try it out!
'abc'"
"def"
(\r\n\t..)
+-
irb(main):008:0> 'abc' + 'def' => "abcdef"
irb(main):010:0> 'abc'.concat('def')
=> "abcdef"
irb(main):009:0> 'abc' - 'def'
NoMethodError: undefined method `-' for "abc":String
var1 = 'stop' var2 = 'foobar'
var3 = "aAbBcC"
var4 = ' '
puts var1.reverse #
puts var2.length #
puts var3.upcase #
puts var3.downcase #
puts var4.strip #
sprintf()
printf()
C
%s, %d, %f..
i1 = 123f1 = 456.789printf(' %d ', i1) # 123 printf('%0.5d', i1) #00123printf('%3.5f', f1) #456.78900
1
show
1
puts 'Hello there, and what\'s your name?'name = gets.chompputs 'Your name is ' + name + '? What a nice name!'puts 'Pleased to meet you, ' + name + '. :)'
ruby xx.rb
irb(main):001:0> 'abc123'.upcase => "ABC123"
irb(main):002:0> 'abc123'.class
=> String
irb(main):003:0> 'abc123' == String.new('abc123')
=> true
irb(main):004:0> 5.times{puts '?'}
?
?
?
?
?
=> 5
() Variable
a = 100b = 10.5a * b #= 1050.0c = 'SO'd = 'GO'c+d #= "SOGO"
$
i1 = 123puts "Iam#{i1}" #"Iam123"
Conversions
var1 = '2'var2 = 4var3 = 4.5var1.to_i * var2 #= 8 var1.to_f * var3 #= 9.0 var3.to_s + var1 #=
Constant
irb(main):001:0> foo = 1 => 1
irb(main):002:0> foo = 2
=> 2
irb(main):003:0> Foo = 1
=> 1
irb(main):004:0> Foo = 2
(irb):4: warning: already initialized constant Foo
=> 2 #OK
irb(main):005:0> RUBY_PLATFORM
=> "i686-linux"
irb(main):006:0> ENV #
Nil
false/0/('')
irb(main):001:0> nil=> nilirb(main):002:0> nil == false=> falseirb(main):003:0> nil == ''=> false
#
#
Array
http://ruby-doc.org/core-1.8.7/classes/String.html
[1,2,3,4] [1,'abc',false,[nil,nil]] #[1,2,3,4].reverse # [4, 3, 2, 1][1,'abc',false,[nil,nil]].size # 4[1,'abc',false,[nil,nil]].flatten # [1, "abc", false, nil, nil]
[n] n
[n..m] nm
[n...m] nm-1
[n,len]nlen
arr = [1,2,3,4,5,6,7,8,9]p arr[2..3] #[3, 4]p arr[2...4] #[3, 4]p arr[2,2] #[3, 4]
[1,2,3] + [4,5,6] # [1, 2, 3, 4, 5, 6][1,2,3].concat [4,5,6] # [1, 2, 3, 4, 5, 6]
(1)
ossf=['whoswho','openfoundry','org']ossf [65, 98, 99, 100, 101, 49, 50, 51, 72, 71]'Abcde123HG'[1]=> 98
Hash
h = {:abc => 123, 'def' => 456}#= {"def"=>456, :abc=>123}h[:abc]#= 123h['def']#= 456
Symbols
h2 = { :abc => 123, 'abc' => 456}#= {"abc"=>456, :abc=>123}:abc.object_id#= 263138 #'abc'.object_id#= 84140440'abc'.object_id#= 84137350 #
PUTS/P
irb(main):011:0> h = {:abc => 123}=> {:abc=>123}irb(main):012:0> p h{:abc=>123}irb(main):013:0> puts habc123irb(main):014:0> puts :ossfossfirb(main):015:0> p :ossf:ossf
>
=
==
!=
AND &&
OR ||
NOT !
If end
Unless end
Case when end
if
puts ""your_money = gets.to_iif your_money >= 100000 puts ""elsif your_money >= 22000 puts "22K"else puts ''end
unless
elsifif
CASE
aaa = [1 ,'abc', 1.3]p aaaprintf('?')idx = gets.to_icase aaa[idx] when String puts "" when Integer puts "" when Float puts "" when Numeric puts '' else puts ""end
EXPRESSION ? (True Condition):(False Condition)
a = 10; b = 100a > b ? ("#{a} > #{b}"):("#{a} < #{b}") #=> "10 < 100"
10.times do puts ''end
for i in 1..10 puts iend
x = 100while x > 10 x = x - 10 puts xend
x = 100until x 0end5.times do print ':' num = gets.chomp.to_i if num == randnum puts '~YEAH!' break end if num - randnum >= 10 puts "" elsif (num - randnum) < 10 && (num - randnum) >= 1 puts '' elsif randnum - num >= 10 puts '' else puts '' endend
phone = "002-2882-5252"if phone =~ /(\d+)\-(\d+)\-(\d+)/ area = $1 first = $2 second = $3endp [area, first, second]
Method
(Instance Method)
(Class Method)
(Instance Method)
new
(self)
'abcdef'.reverse #=> "fedcba"
(Class Method)
(self)
.new
irb(main):009:0> a = Date.today=> #irb(main):010:0> puts a2010-05-22
sprintf("%d %04x", 123, 123) #=> "123 007b
Def ..end
return
returnreturn
def hello(name) sprintf(' %s', name)end
def(..)
def showmanytimes(text2show, times = 10) #=> OK! times.times{puts text2show}enddef showmanytimes(times = 10, text2show) # => times.times{puts text2show}end
? !
?boolean
!
irb(main):001:0> [1,2,3,4].empty?=> falseirb(main):002:0> [1,2,3,4,[5,6]].flatten=> [1, 2, 3, 4, 5, 6]
(Class)(Instance)
Ruby!
'OSSF'.class => String
class Duck def initialize(name) @name = name end def quack # "#{@name} is quacking!" endendd = Duck.new('!')puts d.quack #! is quacking!
!
class Car @@amount = 0 def initialize(name) @name = name @@amount += 1 end def name=(val) @name = val end def name @name end def self.amount @@amount endendc1 = Car.new('' ); c2 = Car.new('' )c3 = Car.new('Focus'); c3.name = 'Focus ST'puts " " + Car.amount.to_s + " "
class Car @@amount = 0 def initialize(name) @name = name @@amount += 1 end attr_accessor :name def self.amount @@amount endend
class Car @@amount = 0 def initialize(name) @name = name @@amount += 1 end def name=(val) @name = val end def name @name end def self.amount @@amount endend
=
attr_accessor
attr_writer def xxx=(val) end
attr_reader def xxx end
Public/Protected/Private
Public
Protected()
Private()
/
class Abc def pub ... end def priv ... end def prot ... endprivate :privpublic :pubprotected :protend
class Abcpublic def pub ... endprivate def priv ... endprotected def prot ... endend
=
Object
(superclass)
(subclass)
class Vehicle attr_accessor :tiresendclass Tire attr_accessor :sizeendclass Car < Vehicle def initialize(name) @tires = [] 4.times{@tires [11, 12, 13, 14, 15, 16]arr.select{|a| a > 3} #=> 3 [4, 5, 6]arr.reject{|a| a>3} #=> select[4,5,1,2,3].sort{|a, b| a b} #=>
Code Block
arr1 = ['abc','whoswho.openfoundry.org','OSSF']arr1.sort_by{|w| w.length}# #=> ["abc", "OSSF", "whoswho.openfoundry.org"]arr2 = [5,10,15,20,25]arr2.inject{|sum, x| sum += x } #=> 75
Code Block
#fc = open('abc.html','w')fc.puts('').....fc.puts('')fc.close ##Code Blockopen('abc.html','w') do |fc| fc.puts('') ..... fc.puts('')end #close
3
code block/inject
3
def my_str_arr_processer(arr) return arr.inject(''){|s, a| s.concat(a.upcase.reverse)}endp my_str_arr_processer(['ab', 'c', 'g88'])
4
String
find_capital_letters
:65~90
each_charbytes.to_a
4
class String def find_capital_letters s2r = '' self.each_char{|c| cc = c[0].to_i s2r.concat(c) if cc >= 65 && cc 'Red', :width => 100)#Ruby Programmingputs tag_with_html('td', 'Ruby Programming', {:bglocor => 'Red', :width => 100})#
Exception
begin .....rescue StandardError => ex#ex p ex #errorensure ..... #end
Exception
rescue
$!$@
Module
:(Singleton)
(Name Space)
Mix in
Module for Singleton Class
module HtmlHelper HTML_ESCAPE = { '&' => '&', '>' => '>', ' 'abc', 1 => 'Ubuntu'}hb = {:first => 'RedHat', :second => 'Suse'}p fetch_and_reverse(aa, 1) #"urawAoduyR"p fetch_and_reverse(ha, 0) #"urawAoduyR"p fetch_and_reverse(hb, :second) #"esuS"
arr[]:reverse
Metaprogramming
define_method
class Movie def initialize(id, name) @id = id @name = name end QualityNames = [:fullhd, :hd, :sd] # fullhd_movie_file, hd_movie_file, sd_movie_file # QualityNames.each do |qt| define_method "#{qt.to_s}_movie_file".to_sym do return "/movies/#{qt.to_s}/#{@id}.mp4" end endenda = Movie.new(123,'')puts a.hd_movie_file #/movies/hd/123.mp4
Domain-Specific Language
Class MyApp < Sinatra::Base get '/books/*.*' do # matches /books/ruby-guide.html end get '/rooms/:id/index.html' do # matches '/rooms/123/index.html endend
HTTPWEB
Method Missing
class Wheel attr_accessor :radius def initialize(radius) @radius = radius endendclass Car attr_accessor :wheels def initialize @wheels = [] 4.times{@wheels 300end
URL
*.*splash
get '/books/*.*' do # matches /books/ruby-guide.html params["splat"] # => ["ruby-guide", "html"]end
ERB Template
Code Blockerb
symbol
erb
views
Class MyApp < Sinatra::Base get '/' do @page_title = "!!" erb :index#index.erb, layout.erblayout endend
template
views , index.erb
# myapp.rbrequire 'rubygems'require 'sinatra'get '/' do erb :indexend
:index.erb
Sinatra app
ERB
layout
false, :locals => {:post => @post}%> rendererb
LAYOUT file
HTML
layout.erb
erb:layout => :layout
LAYOUT file
#yielderbrender
Template
get '/array' do @arr = ["aaa","bbb","ccc","ddd"] erb :arrayend
POST FORM
get '/' do erb :indexendpost '/query' do params[:keyword]end
6
http://zonble.net/etc/bw.php
String#gsubBLOCK'abc123def123GGG'.gsub('123', '456')=>
"abc456def456GGG"6#t6.rbrequire 'rubygems'require 'sinatra'get '/'
do erb :indexendpost '/' do @text =
params[:text2parse].gsub(params[:word], "#{params[:word]}") erb
:postend6#index.erb
#post.erbActiveRecord ORM ?ORM: Object-Relational Mapping (table)
(classe) (row) (object) (column) (object attribute)-DB
railsrails MyPostcd MyPostscript/generate model PostDB
db/migrate.rbclass CreatePosts < ActiveRecord::Migration def
self.up create_table :posts do |t| t.string :author t.string
:subject t.text :message t.timestamps end end def self.down
drop_table :posts endendDBrake db:migratePost
DBConsolescript/consoleIRBrailsloadCRUD
post = Post.newClass
methodPost.find#idPost.create#SAVEPost.new#SAVEInstance
methodpost.savepost.update_attributes#post.destroyCRUD
post = Post.newp = Post.new(:author => 'OSSF', :subject =>
'RUBY', :message => '~~~~')p.savep.id # 1puts Post.count # 1p1 =
Post.find(1)p1 = Post.find_by_author('OSSF')p1.subject #
RUBYp1.update_attributes(:author => '', :message => '!!~~')p
p1p1.destroyputs Post.count:DSLfind_by_attrname
find_all_by_attrname Model Validation
validates_presence_ofvalidates_length_of, :in,
:minimum..()validates_numericality_ofvalidates_uniqueness_ofvalidates_format_of:validatesauthorlength3subject5~30rake-RubymakeDSLnamespace
:gameclub do desc "" task :daily_remove => :environment do
Billboard.should_remove.each do |bbs| if bbs.destroy puts
"ID#{bbs.id}, #{bbs.full_url}" else puts "ID#{bbs.id},
#{bbs.full_url} !" end end endendrake gameclub:daily_removeDB
Migration? Ruby
Schema()Sinatraviewsapp.rbviews/layout.erbviews
Representational State Transfer Roy Fielding 2000 SOAPXML-RPC Web
Service API , AmazonYahoo!Google API 7
ActionsURLVERB/postsget/postspost/posts/:idgetshow/posts/:id/editget/posts/:idput/posts/:id/deleteget/posts/newgetREST-STYLE
URL
PATTERNURL/VERB/postsget/postspost/posts/:idget/posts/:id/editeditget/posts/:idput/posts/:id/deletedeleteget/posts/newnewgetDB(ORM)requirelibrequire
'rubygems'require 'sinatra'require 'active_record'$DBCONFIG =
YAML::load
File.open("config/database.yml",'r').readActiveRecord::Base.establish_connection
$DBCONFIG["development"]Dir.glob('app/models/*.rb').each{ |f|
require f}get '/' do redirect '/posts'endCONTROLLERget '/posts/new'
do #new @post = Post.new erb :newendget '/posts' do #list @posts =
Post.all erb :indexendCONTROLLERput '/posts/:id' do #update puts
"put #{params.inspect}" @post = Post.find(params[:id].to_i) if
@post.update_attributes(:author => params[:author], :subject
=> params[:subject], :message => params[:message]) p @post
redirect "/posts" else erb :edit endendCONTROLLERget '/posts/:id'
do #show @post = Post.find(params[:id].to_i) erb :showendget
'/posts/:id/delete' do #delete @post = Post.find(params[:id].to_i)
@post.destroy redirect "/posts"endpost '/posts' do #create puts ""
@post = Post.new(:author => params[:author], :subject =>
params[:subject], :message => params[:message]) if @post.save
redirect "/posts" else erb :new endViews#new.erb {:post =>
@post}%>#edit.erb {:post => @post}%>VIEWS#_form.erb
VIEWS#_post_err.erb : VIEWS#index.erb ID DEL
VIEWS#show.erb