2015年1月25日 星期日

2014.12.27 & 2015.01.25 開開心心學Ruby

ruby是一種物件導向程式語言
Ruby on Rails 是一種使用Ruby建構出來的網站開發框架(Web Framework)

ruby -v 查詢所安裝的ruby版本
gem package_name install '安裝套件
gem env   '查詢套件安裝到哪gem install rails 安裝rail套件
5.times{
puts "hello, ruby" #印出5次hello, ruby
}

變數(variable)
區域變數(local variable,只存在在一個action中)
    X=1(X的值設定為1)
全域變數(global variable所有程式都可以用,但不常用,容易汙染其他套件)
    $variable
實體變數(存在在同一個檔案中,任何action皆可取用)
    @variable
類別變數
    @@ variable

指定變數內容
a=1
x,y,z=1,2,3

常數Constrant
大寫字母開頭,而且它的內容可以被改變

Q:常數與變數的差別?A:常數以大寫字母開頭

保留字(reserved)與關鍵字(keyword,建議不要用)可以定義但不能用

邏輯與流程控制(ruby不用括號和分號)
age = 17
if age>18
  puts "adult"
else
  puts "kids"
end

只有falsenil(空的,其他程式語言稱為NULL)是假的
空陣列是true

if..elsif..end
unless = if not (除非、如果不要)

weather = "sunny"

if  not weather == "sunny"
puts "Great"
end
與底下這段程式相等
unless weather == "ranny"
puts "Great"
end

if可以丟到最後
weather = "sunny"

if weather == "sunny"
puts "Great"
end
與「puts "Great!" if weather == "sunny"」相等

case..when

if age > 0 && age <= 3
        puts "baby"
與底下這段相等
case age 
when 0..3(0~3)
        puts "Baby"

a || = 'a' (|| a or)
a || = 10 (若a沒有設定的話,a的值就設定為10)
與「a = a || 10」

在程式語言中1個等於(=)是指定值的意思
a = 1        (a的值指定為1)
a = a + 1  (a的值指定為a+1)
a += 1
puts a

註解
#single line(單行註解)
=began  ..  =end(多行註解)

迴圈與迭帶(Loop and Interation)

for..in..end
friends = ["k" , "b" , "c"]
for friend in friends
    puts friend
end

while .. end
x=0
while X<10
        puts x
x += 1
end

until = not while

times印幾次

upto downto
1.upto(10) do | i |
    puts "hi, ruby #{ i }"
end

10.downto(1) do | j |
    puts "hi, ruby #{ j }"
end
執行結果:

each:
friends=['a' , 'b' , 'c']

friends.each do |friend|
  puts friend
end
與底下相等,差別在於,如果有回傳值的話,建議使用底下的寫法
friends=['a' , 'b' , 'c']

friends .each{ | friend |
    puts friend
}
執行結果:

each_with_index:
friends=['a' , 'b' , 'c']

friends.each do | friend |
  x += 2
  puts "#{x} #{ friend }"
end
與底下這段相等
friends=['a' , 'b' , 'c']

friends.each_with_index do | friend , y |
  puts "#{ y+1 } #{ friend }"
end
執行結果:

數字
整數除法 10 / 3 無條件捨去
(10 / 3.0 10.0 / 3就會出現完整的小數點)

單引號' '與雙引號" "
age=17
puts "my age is #{age}"
(age帶入)
puts 'my age is #{age}'
(直接印出)
執行結果:

%q()               %Q()
代表單引號 代表雙引號
括弧可以替換成任何成對的符號

字串替換string interpolation
puts "my age is #{age}"

陣列Array.new VS []
陣列內不用擺放相同資料型態
%w 替換成字串
p= %w(1 2 3 4 5)
friends=["aa" , "bb" , "cc"]
puts friend[0]
puts friends.first
puts friends.last

f2 = %w(aa bb cc)
p f2
執行結果:

練習題:
請試著由小到大排序陣列[1,3,4,1,7,nil,7],並移除nil以及重複的數值。
ANS:
a=[1,3,4,1,7,nil,7]
p a.compact!.sort.uniq

.compact!  移除nil
.sort  由小到大排序(若陣列有nil就不能排序)
.uniq 移除重複值

練習題:
1~52取出5個不重複的數字
ANS 1:
p (1..52).to_a.shuffle.first(5) #產生1~52 to_a 轉成陣列 shuffle打散陣列 取出前五個
ANS 2:
p (1..52).to_a.sample(5)  #產生1~52 to_a 轉成陣列 取樣5
sleep 1 # 休息1

Hash
a={:name=>'eddle'}#
a={name:'eddle'} #
p a
p a[:name] #取出name的值 eddle
執行結果:
a={name:'eddle'} 
p 1.class
p :name.class
執行結果:


範圍
(1..10) vs (1…10)
p (1..10).to_a
p (1...10).to_a
執行結果:

練習題:
從1加到100總和
ANS1:
sum = 0
(1..100).to_a.each do |i|
sum += i
end
p sum

ANS 2:
p (1..100).to_a.inject {|sum, i|} sum + i}

ANS 3:
p (1..100).to_a.inject(&:+)

方法 Methos VS 函式 Function
Method 操作物件,通常不會有回傳值
if "gg".empty?  end  操作字串的方法
if empty("gg")
end

Function 要有輸入值和輸出值

def greeting(name, age)
  puts "hi,#{name}, I am #{age} years old"
end
greeting ("eddle", 18)
greeting "eddle", 18   #小括號可以省略

def is_adult?(age)
  if age >=18
    true  #不用寫return
  else
    false
  end
end
p is_adult?(20)
與底下這段相等
def is_adult?(age)
  age >=18
end

? 和!是程式的一部分
回傳值不用寫return

yield
暫時交控制權移交給do..end
def do_something
puts "1"
yield "xyz"
puts "2"
end

do_something do |i|
puts "hello #{i}"
end
執行結果:

Proc
my_square = Proc.new{|x| x**2}

#呼叫Proc的方法
puts my_square.call(10)
puts my_square[10]
puts my_square.(10)
puts my_square === 10

Proc VS block
Proc是物件的block
block不是物件

物件導向程式設計
物件 = 狀態 + 行為
最上層物件 = Object

p "hello".class.superclass.superclass

例:
class 人屬
end
class 智人<人屬
me= 智人.new

class Animal
def sleep
puts "ZZZZZ"
end
end

class Dog < Animal
def sleep
puts "XXXXX"
end
end

class Cat < Animal
end

dd = Dog.new
dd.sleep
執行結果:


p Dog.superclass.superclass
p Dog.superclass.superclass.superclass
p Dog.superclass.superclass.superclass.superclass
執行結果:

class ClassName < ParentClass #類別名稱要使用常數
end

初始化
class Dog
def initialize(name)
             @name=name        
end
def greeting
puts "hello, #{@name}"
end
end

dd=Dog.new("lucky")
dd.greeting
執行結果:


Book.new(title:"ruby",author:"eddie")

實體變數與類別變數
類別變數
class Human
      @@count = 1
      def initialize(name)
                @@count+=1
                @name = name
end
def total
        return @@count
end
end

Human.new
Human.new
Human.new
Human.new
Human.new
Human.new
P a.total

self= current object
class Dog
def greeting
puts "hello, #{self}"
end
end

Dog.new.greeting
執行結果:

實體方法與類別方法
藍圖、模具 不須New就可直接操作
類別方法可以產出實體方法

class Dog
 def sleep #實體方法 puts "ZZZ"
end
 def self.fly #類別方法 puts "I can fly"
end
end

dd=Dog.new
dd.sleep
Dog.fly

存取控制:public protected,private method

class Human
        def hi
                puts "gg"
end
end

g=Human.New
g.hi

class Human #錯誤 private
def hi
puts "gg"
end
end

g=Human.New
g.hi

class Human #正確 def hello
secret_hi
end
private
def secret_hi
puts "gg"
end
end

g=Human.new
g.hello

class Human
        def hi
                puts "gg"
end
private :hi,:go
end

g=Human.New
g.hi

puts是private method
在ruby裡 99.9%的protected都是在寫private

類別也是物件
在ruby中所有東西都是物件

class Human
end

def Human.hello
    puts "hi"
end

Human.hello

class Human
  def self.hello #在hello本身定義類別方法
    puts "hi"
  end
end
Human.hello
class Human
  def initialize(name)
    @name=name
   
  end
  def name
    @name
  end
end

h=Human.new("eddie")
puts h.name #getter

class Human
  def initialize(name)
    @name=name
   
  end
  def name=(new_name)
    @name=new_name
  end
end

h=Human.new("eddie")
puts h.name #getter
h.name="kao" #setter

puts h.name

class Human
  attr_accessor:name
  def initialize(name)
    @name=name   
  end
end
eddie=Human.new('eddie')
puts eddie.name
eddie.name='kao'

class Human
  def initialize(name)
    @name=name   
  end
end
p Human.instance_methods(false)


open class
2個同名的method不會覆蓋會合併

class Fixnum #5是fixnum
  def days
    return self
  end
  def ago
    "12345"
  end
end

puts 5.days.ago


class Fixnum
  alias_method :old_plus,:+
  def +(n)
    self.old_plus(n)
  end
end

p 1+1

class String #"a1234567899"是String
  def is_valid_id?
    true
  end
end

if "a1234567899".is_valid_id?
  puts "yes"
end

模組
class Animal
end

module Flyable
        def fly
"I can fly"
end
end

class Animal; end

class Dog < Animal
include Flyable
end
d=Dog.new
d.fly#模組無法繼承、實體化

module Flyable
  def fly
    puts "I can fly"
  end
end
class Dog
  include Flyable
end
Dog.new.fly

執行結果:

module Flyable
  def fly
    puts "ggg"
  end
end
d.fly

module ActiveRecord
  class Base
    def awesome
      puts "good"
    end
  end
end
a= ActiveRecord::Base.new
a.awesome
(awesome不會衝突)

Mixin 單線繼承
include
module方法引進成實體方法
v.s. extend
塞入幽靈空間,變成類別方法

module Flayable
  def fly
      puts "I can Fly"
  end
end
class Dog
  extend Flayable
end

Dog.fly