打造Ruby學習環境有以下三種方法


1.網路連上https://www.nitrous.io/,需註冊才可使用線上版

2.Ubuntu OS,指令為 sudo apt-get install ruby

如果是選擇此的人,需再安裝打程式碼的記事本

例如:Vim 、 Emacs 、 Sublime text... 等等

3.Mac電腦 


Ruby相關社群


RubyConf Taiwan

Ruby Tuesday

Rails Girls Taipei


有裝Ruby終端機命令


gem install 包裹名 >>安裝套件

gem env >>安裝ruby細項

ruby 檔名.rb >>執行ruby程式


 相關觀念 


常數 大寫開頭 / 變數 小寫開頭

直接宣告變數 區域變數:存活只在方法(function)之內

$宣告變數 全域變數:存活在不同方法(function),跟類別變數類似

@@宣告變數  類別變數:存活在不同方法(function),跟全域變數類似

以下為範例

class MyClass
   @@value = 1
   def add_one
     @@value= @@value + 1
   end
   
   def value
     @@value
   end
 end
 instanceOne = MyClass.new
 instanceTwo = MyClass.new
 puts instanceOne.value
 instanceOne.add_one
 puts instanceOne.value
 puts instanceTwo.value

結果

 1
 2
 2

@宣告變數 實體變數:存活在不同方法(function),但只能在方法(function)內設值才有傳入

以下為範例

 class MyClass
   @one = 1
   def do_something
     @one = 2
   end
   def output
     puts @one
   end
 end
 instance = MyClass.new
 instance.output
 instance.do_something
 instance.output

結果

 nil
 2

實體變數參考網址:http://rpg0822.pixnet.net/blog/category/48491

程式碼參考網址:http://zh.wikibooks.org/zh-tw/Ruby_Programming/Syntax/Classes#.E5.AF.A6.E9.AB.94.E8.AE.8A.E6.95.B8.28Instance_Variable.29

只有false和nil是假的,其餘都是真的

# >>單行註解

begin  end >>多行註解

|| >>OR

a||=10  >>如果a沒設定就設定10

a[:name] >>把name做標誌

private 呼叫不能有小數點

protected 呼叫能有小數點,用的方式99%跟private很像

include 引進來當作實體方法

extend 塞入幽靈空間成類別方法 


程式碼


在Ruby有如果不是判斷式,格式如下

unless 條件式

        .......

end

 >>等同於if not 條件式

         .....

end

當然也會有如果判斷式,格式如下

......   if 條件式 end

>>等同於 if  條件式 ....  end


如果要針對不同條件做某事,在Ruby的格式比別家程式碼有些不同

case

when 條件

        ...

when 條件

        ...

else

        ...

end

>>類似於switch case


想要把顯示內容或是程式執行結果執行幾次,可以用times方法

數字.times{...}

數字.times 變數


在Ruby陣列有兩種,分別為Array.new和[],以下為新增範例

arr_new = Array.new(2,[0,0])

arr = [[0, 0], [0, 0]]

p arr==arr_new #true

看似相同但在改值後發生變化

arr_new[0][0] = "a" 

p arr_new #[["a", 0], ["a", 0]]

arr[0][0] = "b" 

p arr #[["b", 0], [0, 0]]

這是花生什麼事,為何Array_new不是改一個,於是我先把arr部分拿掉繼續測試

arr_new[1][0]="a"

p arr_new #[["a", 0], ["a", 0]]

代表前面[1]或[0]對他無動於衷,接著開始懷疑這東東

arr_new.each do |item|

   p item.object_id

#70189242266200

#70189242266200

end

不會吧,竟然二維中哪個一維陣列都是指向同一個ID

因此在使用array new,別放集合類東西,才不會導致改值出現錯誤

array new,[]參考網址:http://stackoverflow.com/questions/4601652/ruby-array-creation-array-new-vs 


在Ruby很常用each do方法把變數傳入陣列中

陣列.each do |變數|

 

        puts "#{變數}"

 

end 

 也可以用以下方法得知index值

陣列.each_with_index do |變數|

 

        puts "#{變數+1}"  >>因為index以0開始,如要1開始要x+1

 

end


以前在學別家程式語言,難免會寫到Random,接著會是寫上100到200行之間指令,但在Ruby只有下面這行

p (1..52).to_a.sample(5)

p為輸出,(前數..後數)是Random範圍,to_a意思是轉成陣列,sample(數字)就是抽出幾個數字

然而在Ruby範圍有兩點和三點,但是意思卻天差地遠

(1..10)  >>1~10

(1...10)  >>1~9


?類似Id,回傳是布林值

def is_adult?(age)

   age >= 18 

end

 if is_adult?(29)

   puts "ok"

end

其實把問號刪掉,程式還是可以過,跟if運作一樣

def is_adult(age)
     age >= 18
end

if is_adult(29)
     puts "ok"
end

!會改變值,會把原本值改變,在運用上要特別小心

name = "eddie"

p name.upcase!  #EDDIE

p name             #EDDIE

其實把驚嘆號刪掉,程式還是可以過,但結果卻不一樣

name = "eddie"

p name.upcase  #EDDIE

p name      #eddie

?和!參考網址:http://zh.wikipedia.org/wiki/Rubyhttp://zh.wikipedia.org/wiki/Ruby


當我們僅打puts "hello",不禁好奇hello是算在哪個類別,這時可打以下這些

 

p "hello".class   >>hello是在String的類別內

 

p "hello".class.superclass   >>hello是在String,而String是在Object的類別內

 

p "hello".class.superclass.superclass    >>hello是在String,而String是在Object,那Object是在BasicObject類別內

 

p self.class.private_methods.sort  >>想知道self有哪些方法,以順排列顯示

 

以樹狀圖可知之間關係

BasicObject

    |

  Object     

    |

  String

    |

  Hello


在別家程式語言常寫class,當然在Ruby也不例外

class 變數名稱  >>變數名稱以大寫開頭為class物件

        ...

end

至於繼承寫法倒是挺讓人意外

class 變數名稱 <  類別名稱    >>繼承

        ...

end 

關於 < 他有看似很像的兄弟是 <<

class << self     >>附加

其實這樣看可能不是很懂,那以陣列來說就很明顯

先設兩個陣列值,然後讓a附加b內容後顯示a

a=[1,2,3]

b=[4,5]

a << b

p a

結果為

[1,2,3,[4,5]]

<<參考網址:http://sls.weco.net/node/10732


在Ruby有初始值initialize,以下為範例

class Book

  def initialize(name)

    puts "hello, #{name}"

  end

end 

Book.new("eddie")

以下程式碼是把上方改成實體變數和顯示參數的go方法,透過實體化h把go方法實施

class Qa

  def initialize(name)

    @name=name

  end

  def go

    @name     <<等同於return @name

  end

end

h=Qa.new("PP")

puts h.go


我們常用的三大public,protected,private,在Ruby卻有意外的是

private 呼叫不能有小數點

class Pri

  def hello

    secret_hi     >>不能用self.secret_hi

  end

  private

  def secret_hi

    puts "gg"

  end

end

g=Pri.new

g.hello

g.send(:secret_hi)

g.send(:send,:secret_hi)

但是在protected上可以接受小數點

class Pria

  def hello

    self.secret_hi

  end

  protected

  def secret_hi

    puts "gg"

  end

end

g=Pria.new

g.hello

當然在public是允許使用小數點 

class Priat

  def hello

    self.secret_hi

  end

  public

  def secret_hi

    puts "gg"

  end

end

g=Priat.new

g.secret_hi 


有時會把class留白,然後將他實體化(範例中h),接著用方法延伸,再來透過h.hi來執行方法

class Rabby

end

h=Rabby.new

def h.hi

   puts "U0A0U"

end

h.hi

等同於

class Rabby
     def hi
           puts "U0A0U"
     end
end

h=Rabby.new
h.hi


類別也是物件

class Rabby

end

def Rabby.hi

   puts "U0A0U"

end

Rabby.hi

把上面改成下面這樣也能過,因為類別也是物件

class Rabby

  def self.hi    <<self指class的Rabby

     puts "U0A0U"

  end

end

Rabby.hi


puts 1.send(:+,2)   <<Ruby 1+2=3 


以下是我們取值和顯示的程式碼

class Ea
     def get(name)
          @name=name
     end
     def put
          @name
     end
end
h = Ea.new
h.get("LO")
puts h.put

如果每次都要寫取值顯示這兩個方法,其實是挺麻煩的(造成枯燥煩悶),於是Ruby多一個attr_accessor,讓變數可以付予寫和讀功能

class Ea
     attr_accessor :name
end
h=Ea.new
h.name="LO"
puts h.name

以下是增加初始值寫法,會發現兩種不同結果

class Ea

  attr_accessor :name   <<可讀可寫

  def initialize(name)

    @name=name

  end

end

h=Ea.new("Yo")   <<initialize

puts h.name   <<initialize getter

h.name="LO"  <<setter

puts h.name   <<getter

attr_accessor參考網址:http://stackoverflow.com/questions/4370960/what-is-attr-accessor-in-ruby


有時在特殊狀況我們會想用別號,以下是把+物件取為old_plus別號

class Fixnum 

  alias_method:old_plus,:+     <<別號方法:取別號,:物件名稱

  def +(n)

     self.old_plus(n)

  end

end 

p 1+1


既然有class,那當然少不了module這東西

module不能被繼承

module 模組名稱

        ...

end

以下是module的include範例

module Fly

  def fly

    puts "I can Fly!"

  end

end

class Ani; end

class Bird < Ani

  include Fly   <<不是呼叫,而是把module內東西插入,實體方法

end

d=Bird.new

d.fly

在上方Fly這個module範例,不禁好奇一下這程式碼是如何運作,還有那些物件到底身在何處,所以我們可以用下面寫法去找到他 

p class/module名稱.ancestors  <<結構

p Bird.ancestors   顯示結果   [Bird,Fly,Ani,Object,Kernel,BasicObject]

p Fly.ancestors     顯示結果   [Fly]

既然有include,那也要提類似include但運作不一樣的extend

以下是module的extend範例

module Fly

  def fly

    puts "I can Fly!"

  end

end

class Ani; end

class Bird < Ani

  extend Fly    <<塞入幽靈空間,類別方法

end

Bird.fly

從這兩個(include,extend)可知,包含執行是需要實體,但繼承執行不需要實體,不禁覺得extend和<真有異曲同工之妙

include和extend參考網址:http://www.railstips.org/blog/archives/2009/05/15/include-vs-extend-in-ruby/


p Class.instance_methods   <<class結構方法

p Module.instance_methods   <<module結構方法

搜尋Ruby Object Model可以找到關係圖


有時因為程式碼過長,怕會有重複名稱,我們能用::來指定(是這老爸帶的小孩) 

module Do

  class Doa

    def awe

      puts "food"

    end

  end

end

a=Do::Doa.new   <<避免有重複Doa名稱於是用::,代表在Do底下Doa

a.awe


method_missing(,,,,)   <<如果傳入參數找不到,顯示相關訊息

以下程式碼參考網址:http://ruby-doc.org/core-2.1.0/BasicObject.html

class MyObjectSystem < BasicObject
  DELEGATE = [:puts, :p]

  def method_missing(name, *args, &block)
    super unless DELEGATE.include? name
    ::Kernel.send(name, *args, &block)
  end

  def respond_to_missing?(name, include_private = false)
    DELEGATE.include?(name) or super
  end
end

以下個人讀解:   (可能有錯 ˊ ˇ ˋ)

一個名叫MyObjectSystem繼承BasicObject。

變數DELEGATE為陣列,存入puts和p標誌(標籤)。

宣告method_missing(傳入name和*arg和&block),

判斷傳入name變數在DELEGATE是否沒有包含,

沒有就根據之前運作顯示訊息,

有就Kernel送出傳入三個參數。

宣告respond_to_missing?(傳入name和include_private=false),

DELEGATE有包含此name變數或者根據之前運作顯示訊息。

 

後續,因為對*和&不解,於是我又跪拜Google大神求道

*在ruby doc上說明格式

ary * int → new_ary

ary * str → new_string

 也舉了範例

[ 1, 2, 3 ] * 3    #=> [ 1, 2, 3, 1, 2, 3, 1, 2, 3 ]
[ 1, 2, 3 ] * ","  #=> "1,2,3"

&在ruby doc上說明格式

ary & other_ary → new_ary 

也舉了範例

[ 1, 1, 3, 5 ] & [ 1, 2, 3 ]   #=> [ 1, 3 ]

*和&在ruby doc參考網址:http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-2A

 

但是我還是解釋不出前面沒東東該作什麼

接著在某個問答論壇找到*解釋範例

def func2(arg1, arg2,*other_args)
  p arg1.inspect       # => 1
  p arg2.inspect       # => 2
  p other_args.inspect # => [3, 4, 5]
end

func2(1,2,3,4,5)

從這可以得知*有擴展意思,所以當傳入值種類個數大於方法預定,可用*來加長

*問答參考網址:http://stackoverflow.com/questions/3701264/passing-a-hash-to-a-function-args-and-its-meaning

至於&我花長時間爬文終於找到,以下為修改後範例

class Array

  def iterate2!(&code)

    self.each_with_index do |n, i|

      self[i] = code.call(n)

    end

  end

end 

array = [1, 2, 3, 4]

array2 = [2, 2, 3, 4] 

array.iterate2! do |n|

  n ** 2

end

array2.iterate2! do |n|

  n ** 2

end

puts array.inspect    #[1, 4, 9, 16]

puts array2.inspect   #[4, 4, 9, 16]

&在變數名稱前是宣告這是block參數,那block是啥鬼東西,於是用方法來問問這是哪種類別

def what_am_i(&block)

  block.class

end 

puts what_am_i {}   #Proc

哇這Proc不就是SQL所學預存,沒錯,以下是用Proc範例

class Array

  def iterate!(code)

    self.each_with_index do |n, i|

      self[i] = code.call(n)

    end

  end

end 

array = [1, 2, 3, 4]

array2 = [2, 2, 3, 4] 

square = Proc.new do |n|

  n ** 2

end 

array.iterate!(square)

array2.iterate!(square) 

puts array.inspect  #[1, 4, 9, 16]

puts array2.inspect  #[4, 4, 9, 16]

後來我把*那個程式碼改成&

def func2(arg1, arg2,&other_args)

  p arg1.inspect       #1  #2

  p arg2.inspect       #2  #2

  p other_args.inspect  

#  #<Proc:0x007f0b21aab670@text.rb:59>

#  #<Proc:0x007f0b21aab418@text.rb:62>

end 

func2(1,2) do  #59

  #...

end

func2(2,2) do  #62

  #...

end

原來proc內挖個block,0x開頭為記憶體位置,是block存在記憶體位置,記錄檔名叫text.rb,最後把執行行數也記錄,簡單來說proc內會存一或多block

那剛剛舉block和proc範例有何不同,其實看程式碼執行方式就知,proc是共用,但block可各走各的路((啥鬼說詞

像proc需創個實體square,array和array2透過實體square來實施iterate!,而實體都同個當然都是執行proc內定行程

但block不需創個實體,array和array2直接實施iterate!,而行程由各家歡樂定,讓人覺得自由過頭,不過也難怪會在proc class下

proc和&block參考網址:http://rubyer.me/blog/917/

創作者介紹
創作者 o迷苓o 的頭像
o迷苓o

~米漿牛奶~

o迷苓o 發表在 痞客邦 留言(0) 人氣()