如何設計出漂亮的 Ruby APIs

Python015

如何設計出漂亮的 Ruby APIs,第1张

1.Argument Processing

Ruby 使用了 Symbols 和 Hash 来达到虚拟关键字参数(Pseudo-Keyword Arguments)。这种技巧被广泛应用在 Ruby 的函式库和 Rails 中,增加了阅读性,也很容易使用。

def blah(options)

puts options[:foo]

puts options[:bar]

end

blah(:foo =>"test", :bar =>"test")

Ruby 也可以将参数列当成阵列使用:

def sum(*args)

puts args[0]

puts args[1]

puts args[2]

puts args[3]

end

sum(1,2,3)

如此就可以设计出不固定参数列、十分弹性的 API。类似於 C++ 的 function overloading。在 Rails 中也十分常见这样的 API 设计,例如 link_to 就支援了两种用法:

# USAGE-1 without block

<% link_to 'Posts list', posts_path, :class =>'posts' %>

# USAGE-2 with block

<% link_to posts_path, :class =>'posts' do %>

Posts list

<% end %>

搭配虚拟关键字参数使用的话,可以参考 ActiveSupport#extract_options! 这个小技巧取出 Hash 值。

2. Code Blocks

程式区块(Block)是 Ruby 最重要的特色,除了拿来做迭代(Iteration)之外,也可以包装前後置处理(pre- and Post-processing),一个最基本的例子就是开档了,一般程序式的写法如下:

f = File.open("myfile.txt", 'w')

f.write("Lorem ipsum dolor sit amet")

f.write("Lorem ipsum dolor sit amet")

f.close

使用 Block 之後,我们可以将 f.close 包装起来,不需要明确呼叫。只要程式区块结束,Ruby 就会自动关档。程式一来因为缩排变得有结构,二来也确定档案一定会关闭(不然就语法错误了)

# using block

File.open("myfile.txt", 'w') do |f|

f.write("Lorem ipsum dolor sit amet")

f.write("Lorem ipsum dolor sit amet")

end

另一个程式区块的技法,是用来当做回呼(Dynamic Callbacks)。在 Ruby 中,程式区块也是物件,於是我们可以将程式区块如透过”注册”的方式先储存下来,之後再依照需求找出来执行。例如在 Sinatra 程式中:

get '/posts' do

#.. show something ..

end

post '/posts' do

#.. create something ..

end

我们”注册”了两个回呼:一是当浏览器送出 GET ‘/posts’ 时,会执行 show something 的程式区块,二是 POST ‘/posts’ 时。

3. Module

模组(Module)是 Ruby 用来解决多重继承问题的设计。其中有一招 Dual interface 值得一提:

module Logger

extend self

def log(message)

$stdout.puts "#{message} at #{Time.now}"

end

end

Logger.log("test") # as Logger’s class method

class MyClass

include Logger

end

MyClass.new.log("test") # as MyClass’s instance method

Ruby 的 extend 作用是将模组混入(mix-in)进单件类别(singleton class),於是 log 这个方法除了可以像一般的模组被混入 MyClass 中使用,也可以直接用 Logger.log 呼叫。

要将 Ruby 模组的混入成类别方法(class method),也有一些常见的 pattern 模式,可以将模组设计可以同时混入实例方法(instance method)和类别方法,请参阅投影片范例。这在撰写 Rails plugin 时非常常用。

4. method_missing?

Ruby 的 Missing 方法是当你呼叫一个不存在的方法时,Ruby 仍然有办法处理。它会改呼叫 method_missing 这个方法,并把这个不存在的方法名称传进去当做参数。这个技巧在 Rails 的 ActiveRecord 中拿来使用:

class Person <ActiveRecord::Base

end

p1 = Person.find_by_name("ihower")

p2 = Person.find_by_name_and_email("ihower", "[email protected]")

其中 find_by_name 和 find_by_email 就是这样的方法。不过这个技巧不是万能丹,它的执行效率并不好,所以只适合用在你没办法预先知道方法名称的情况下。不过也不是没有补救之道,如果同样的方法还会继续呼叫到,你可以在 method_missing 之中用 define_method 或 class_eval 动态定义此方法,那麼下次呼叫就不会进来 method_missing,进而获得效能的改善。事实上,ActiveRecord::Base 的 method_missing 就是这麼做的。(感谢 BigCat 留言提醒我有此补救之道)

另一个 Missing 方法的绝妙 API 设计,是拿来构建 XML 文件:

builder = Builder::XmlMarkup.new(:target=>STDOUT, :indent=>2)

builder.person do |b|

b.name("Jim")

b.phone("555-1234")

b.address("Taipei, Taiwan")

end

# <person>

# <name>Jim</name>

# <phone>555-1234</phone>

# <address>Taipei, Taiwan</address>

# </person>

搭配了区块功能,就能用 Ruby 语法来写 XML,非常厉害。

5. const_missing

除了 method_missing,Ruby 也有 const_missing。顾名思义就是找不到此常数时,会呼叫一个叫做 const_missing 的方法。现实中的例子有 Rails 的 ActiveSupport::Dependencies,它帮助我们不需要先载入所有类别档案,而是当 Rails 碰到一个还不认识的常数时,它会自动根据惯例,找到该档案载入。

我们也可以利用这个技巧,针对特定的常数规则来处理。例如以下的程式会自动将 U 开头的常数,自动转译成 Unicode 码:

class Module

original_c_m = instance_method(:const_missing)

define_method(:const_missing) do |name|

if name.to_s =~ /^U([0-9a-fA-F]{4})$/

[$1.to_i(16)].pack("U*")

else

original_c_m.bind(self).call(name)

end

end

end

puts U0123 # ģ

puts U9999 # 香

6. Methods chaining

方法串接是一个很常见的 API 设计,透过将方法的回传值设成 self,我们就可以串接起来。例如:

[1,1,2,3,3,4,5].uniq!.reject!{ |i| i%2 == 0 }.reverse

# 5,3,1

7. Core extension

Ruby 的类别是开放的,可以随时打开它新增一点程式或是修改。即使是核心类别如 Fixnum 或是 Object(这是所有类别的父类别) 都一样。例如 Rails 就定义了一些时间方法在 Fixnum 里:

class Fixnum

def hours

self * 3600 # 一小时有多少秒

end

alias hour hours

end

Time.now + 14.hours

Ruby 的物件模型与元编程(Meta-programming)

在 Ruby 中,所有东西都是物件。甚至包括类别(class)本身也是物件。这个类别物件(class object)是一个叫做 Class 的类别所实例出来的物件。而所有的物件(当然也包括类别物件),都有一个 metaclass (又叫做 singleton, eigenclass, ghost class, virtual class 等名字)。定义在 metaclass 里的方法,只有该物件能够使用,也就是 singleton method (单件方法),只有该物件才有的方法。

了解什麼是 metaclass 是 Ruby 元编程的一个重要前提知识。Ruby 元编程最常用的用途,就是因应需求可以动态地定义方法,例如在 Rails ActiveRecord 中常见的 Class Macro 应用。

要能随心所欲动态定义方法的关键重点,就是 variable scope (变数的作用域) 了。例如以下我们透过 class_eval 和 define_method 帮 String 定义了一个 say 方法,注意到整个 variable scope 都是通透的,没有建立新的 scope:

name = "say"

var = "it’s awesome"

String.class_eval do

define_method(name) do

puts var

end

end

"ihower".say # it’s awesome

class_eval 可以让我们改变 method definition 区域(又叫做 current class)。除了本投影片,建议可以阅读 Metaprogramming in Ruby: It’s Allhe Self 和 Three implicit contexts in Ruby 这两篇文章深入了解 self 和 current class。

8. Class Macro (Ruby’s declarative style)

Class Macro 是 Ruby Meta-programming 非常重要的一个应用,例如在 Rails ActiveRecord 中:

class User <ActiveRecord::Base

validates_presence_of :login

validates_length_of :login,:within =>3..40

validates_presence_of :email

belongs_to :group

has_many :posts

end

Ruby鲁比(女子名)英 [ˈrubi]   美 [ˈrubi]

派生词: ruby adj.

1、They got misty-eyed listening to records of Ruby Murray singing 'Danny Boy'.

聆听着唱片里鲁比·默里演唱《丹尼男孩》的时候,他们泪眼模糊。

2、Which has more elements than the Lisp version because you have to extract parameters manually in Perl.

这比Lisp和Ruby的版本,有更多的语法元素,因为在Perl语言中,你不得不手工提取参数。

3、In this article, I used Ruby as an example.

在本文中,我以Ruby为例。

代表人物Ruby,美国模特,照片如下:

扩展资料:

ruby其他意思

n.红宝石,红玉红宝石色,深红色<英>细铅字红葡萄酒

adj.红宝石的红宝石色的

vt.使带红宝石色把…弄红把…涂染成红色

1、The framework is written in the Ruby programming language and includes components written in C and assembler.

该框架是在书面红宝石的编程语言和书面组件包括在C和汇编。

2、A: Have you any idea of the prices of ruby and diamond?

你知道红宝石和金刚石的价格吗?

3、Emerald bracelets and a ruby pendant. Her bracelet was set with emeralds.

一对绿宝石手?和一个红宝石坠子。她的手镯上镶着绿宝石。

Abyssal Scepter 虚空之杖Aegis of the Legion 军团圣盾Amolifying Tome 增幅典籍Archangel's Staff 大天使之杖Athene's Unholy Grall 雅典娜的邪恶圣杯Atma's Impaier 阿塔玛之戟Augment:Death/Gravity/Power 强化:死亡/重力/能量(由维克托初始道具合成)Avarice Blade 贪婪之刃B.F.Sword 风暴之剑Banner of Command 号令之旗Banshee's Veil 女妖面纱Berserker's Greaves 狂战士胫甲Bilgewater Cutlass 比尔吉沃特弯刀*Blackfire Torch 黯炎火炬Blade of the Ruined King 破败王者之刃Blasting Wand 爆裂魔杖Bonetooth Necklace 骨齿项链(雷恩加尔击杀战利品)Boots of Mobility 疾行之靴Boots of Swiftness 轻灵之靴Brawler's Gloves 格斗手套Catalyst the Protector 催化神石Chain Vest 锁子甲Chalice of Haemony 和谐圣杯Cloak of Agiliity 灵巧披风Cloth Armor 布甲Crystalline Flask 水晶瓶Dragger 短剑Deathfire Grasp 冥火之拥Doran's Blade 多兰之刃Doran's Ring 多兰之戒Doran's Shield 多兰之盾Elesa's Miracle 伊丽莎的奇迹Elixir of Brilliance 智慧合剂Elixir of Fortitude 坚韧合剂Emblem of Valor 英勇徽章Enchantment:Alacrity 附魔:欢欣Enchantment:Captain 附魔:统帅Enchantment:Distortion 附魔:失真Enchantment:Furor 附魔:喧哗Enchantment:Homegurad 附魔:家园卫士*Entropy 冰霜战锤(注意是战锤不是之锤)Execution's Calling 死刑宣告Faerie Charm 仙女护符Fiendish Codex 恶魔法典Frozen Heart 冰霜之心Frozen Mallet 冰霜之锤Giant's Belt 巨人腰带Glacial Shroud 冰川护甲*Grez's Spectral Lantern 基渣的幽魂之灯Guardian Angel 守护天使(简称GA)Guinsoo's Rageblade 鬼索的狂暴之刃Haunting Guise 幽魂面具Health Potion 生命药水(小红药)Hexdrinker 海克斯饮魔刀Hextech Gunblade 海克斯科技枪刃Hextech Revolver 海克斯科技左轮枪*Hextech Sweeper 海克斯科技探测器Hunter's Machete 猎人的宽刃刀(打野刀)Iceborn Gauntiet 冰脉护手(冰拳)*Ichor of Illumination 启示灵药*Ichor of Rage 狂怒灵药Infinity Edge 无尽之刃Ionian Boots of Lucidity 明朗之靴(直译过来是“艾欧尼亚的明朗之靴”=。=)Kages Lucky Pick 凯奇的幸运手Kindlegem 燃烧宝石*Kitae's Bloodrazer 吉泰的夺命剃刀Last Whisper 最后的轻语Liandry's Torment 兰德里的折磨Lich Bane 巫妖之祸Locket of the Iron Solari 钢铁烈阳之匣(鸟盾)Long Sword 长剑Madred's Razor 麦瑞德之爪(打野手套,不是早就移除的绿爪!!!)Mana Manipulator 御魔之器Mana Potion 法力药水(小蓝药)Manamune 魔宗利刃Maw of Malmoetius 玛莫提乌斯之噬Mejai's Soulstealer 梅贾的窃魂卷Mercurial Scimitar 水银弯刀Mercury's Treads 水银之靴Mikael's Crucible 米凯尔的坩埚Muramana 魔切Nashor's Tooth 纳什之牙Needlessly Large Rod 无用大棒Negatron Cloak 负极斗篷Ninja Tabi 忍者足具Null-Magic Mantie 抗魔斗篷*Odyn's Veil 奥戴恩的面纱Ohmwrecker 干扰水晶Oracle's Elixir 先知药剂*Oracle's Extract 神谕精粹Overlord's Bloodmail 霸王血铠Phage 净蚀Phantom Dancer 幻影之舞Philosopher's Stone 贤者之石Pickaxe 十字镐*Prospector's Blade 勘探者之刃*Prospector's Ring 勘探者之戒Quicksilver Sash 水银饰带Rabadon's Deathcap 灭世者的死亡之帽Randuin's Omen 兰顿之兆Ravenous Hydra (Melee Only) 贪婪九头蛇(仅近战可用)Recurve Bow 反曲之弓Rwjuvenation Bead 治疗宝珠Rod of Ages 时光之杖Ruby Crystal 红水晶Ruby Sightstone 洞察红宝石Runaan's Hurricane (Ranged Only)卢安娜的飓风(仅远程可用)Runic Bulwark 符文壁垒Rylai's Crystal Scepter 瑞莱的冰晶节杖*Sanguine Blade 血色之刃Sapphire Crystal 蓝水晶Seraph’s Embrace 炽天使之拥Shard of True Ice 极冰碎片Sheen 耀光Shurelya's Reverie 舒瑞亚的狂想曲Sight Ward 侦查守卫Sightstone 洞察之石Sorcerer's Shoes 法师之靴Spirit Stone 精魄之石Spirit Visage 振奋铠甲Spirit of the Ancient Golem 远古魔像之精魄Spirit of the Elder Lizard 蜥蜴长老之精魄Spirit of the Spectral Wraith 破碎幽灵之精魄Statikk Shiv 斯塔提克电刃Stinger 蜂刺Sunfire Cape 日炎斗篷Sword of the Divine 神圣之剑Sword of rhw Occult 神秘之剑Tear of the Goddess 女神之泪The Black Cleaver 黑色切割者The Bloodthirster 饮血剑The Brutalizer 残暴之力The Hex Core 海克斯科技核心(维克托初始道具)*The Lightbringer 光明使者Thornmail 荆棘之甲Tiamat (Melee Only) 提亚马特Trinity Force 三相之力Twin Shadows 双生暗影Vampiric Scepter 吸血鬼节杖Vision Ward 真视守卫Void Staff 虚空之杖Warden's Mail 守望者铠甲Warmong's Armor 狂徒铠甲Will of the Ancients 远古意志Wit's End 智慧末刃*Wooglet's Witchcap 沃格勒特的巫师帽Wriggle's Lantern 瑞格之灯Youmuu's Ghost blade 幽梦之灵Zeal 狂热Zeke's Herald 基克的使徒Zephyr 灵风Zhonya's Hourglass 中娅沙漏