Ruby是一种纯粹的面向对象编程语言。日本的松本由纪子创立于1993年。
您可以在www.ruby-lang.org上的Ruby邮件列表中找到松本松子的名字。松下在Ruby社区也被称为Matz。
Ruby是“程序员最好的朋友”。
Ruby具有与Smalltalk,Perl和Python类似的功能。Perl,Python和Smalltalk都是脚本语言。Smalltalk是一种真正的面向对象语言。Ruby,像Smalltalk,是一种完美的面向对象语言。使用Ruby语法比使用Smalltalk语法容易得多。
Ruby是一个开放源代码,可以在网络上免费获得,但需要许可证。
Ruby是一种通用的,解释性的编程语言。
Ruby是一种真正的面向对象编程语言。
Ruby是一种类似于Python和PERL的服务器端脚本语言。
Ruby可用于编写通用网关接口(CGI)脚本。
Ruby可以嵌入超文本标记语言(HTML)。
Ruby具有干净简单的语法,允许新开发人员非常快速,轻松地学习。
Ruby具有与许多编程语言(如C ++和Perl)类似的语法。
Ruby是非常可扩展的,用Ruby编写的大型程序很容易维护。
Ruby可用于开发Internet和Intranet应用程序。
Ruby可以安装在Windows和POSIX环境中。
Ruby支持许多GUI工具,如Tcl / Tk,GTK和OpenGL。
Ruby可以轻松连接到DB2,MySQL,Oracle和Sybase。
Ruby具有丰富的内置函数,可以直接用于Ruby脚本。
对于执行本教程中探讨的示例,您将需要最新的计算机,如Intel Core i3或i5,至少需要2GB的RAM(推荐4GB的RAM)。您还需要以下软件 -
Linux或Windows 95/98/2000 / NT或Windows 7操作系统。
Apache 1.3.19-5 Web服务器。
Internet Explorer 5.0以上Web浏览器。
Ruby 1.8.5
本教程将提供使用Ruby创建GUI,网络和Web应用程序的必要技能。还将探讨扩展和嵌入Ruby应用程序。
下一章将指导您了解可以获取Ruby及其文档的位置。最后,它指示您如何安装Ruby并准备开发Ruby应用程序的环境。
在线运行
我们已经在线设置了Ruby Programming环境,因此可以在线编译和执行所有可用的示例。你可以学习的同时,在线验证程序。随意修改任何示例并在线执行。
使用我们的在线编译器可在尝试下面的例子CodingGround
#!/usr/bin/ruby -w puts "Hello, Ruby!";对于本教程中给出的大多数示例,您将在右上角的网站代码部分找到一个Try it选项,该部分将带您进入在线编译器。所以只是利用它,享受你的学习。
如果您仍然愿意为Ruby编程语言设置环境,那么我们继续。本教程将向您介绍与环境设置相关的所有重要主题。我们建议您先浏览以下主题,然后继续进行 -
Linux / Unix上的Ruby安装 - 如果您打算在Linux / Unix机器上安装开发环境,请参阅本章。
Windows上的Ruby安装 - 如果您打算在Windows机器上安装开发环境,请参阅本章。
Ruby命令行选项 - 本章列出了可以与Ruby解释器一起使用的所有命令行选项。
Ruby环境变量 - 本章列出了要设置为使Ruby Interpreter工作的所有重要环境变量。
要编写你的Ruby程序,你需要一个编辑器 -
如果您正在使用Windows机器,那么您可以使用任何简单的文本编辑器,如记事本或编辑加号。
VIM(Vi IMproved)是一个非常简单的文本编辑器。几乎所有的Unix机器和Windows都可以使用。否则,您可以使用您最喜欢的vi编辑器来编写Ruby程序。
RubyWin是Windows的一个Ruby集成开发环境(IDE)。
Ruby开发环境(RDE)也是Windows用户非常好的IDE。
交互式Ruby(IRb)提供了一个用于实验的shell。在IRb shell中,您可以立即逐个查看表达式结果。
这个工具与Ruby安装一起,所以你没有什么可以额外的使IRb工作。
只需在命令提示符下键入irb,交互式Ruby会话即可开始如下:
$irb irb 0.6.1(99/09/16) irb(main):001:0> def hello irb(main):002:1> out = "Hello World" irb(main):003:1> puts out irb(main):004:1> end nil irb(main):005:0> hello Hello World nil irb(main):006:0>
不要担心我们在这里做了什么。您将在以后的章节中了解所有这些步骤。
我们假设现在你有一个工作的Ruby环境,你准备好编写第一个Ruby程序。下一章将教你如何编写Ruby程序。
让我们用ruby写一个简单的程序。所有ruby文件将扩展名为.rb。所以,将以下源代码放在test.rb文件中。
#!/usr/bin/ruby -w puts "Hello, Ruby!";
在这里,我们假设你的Ruby解释器在/ usr / bin目录下可用。现在,尝试运行这个程序如下 -
$ ruby test.rb
输出结果如下 -
Hello, Ruby!
您已经看到一个简单的Ruby程序,现在让我们看看一些与Ruby语法相关的基本概念。
Ruby代码中通常忽略诸如空格和制表符之类的空格字符,除非它们以字符string形式出现。然而有时候,它们被用来解释不明确的语句。当启用-w选项时,这种解释会产生警告。
a + b is interpreted as a+b ( Here a is a local variable) a +b is interpreted as a(+b) ( Here a is a method call)
Ruby将分号和换行符解释为语句的结尾。但是,如果Ruby遇到运算符,例如行尾的+, - 或反斜杠,则表示语句的继续。
标识符是变量,常量和方法的名称。Ruby标识符区分大小写。这意味着Ram和RAM是Ruby中两个不同的标识符。
Ruby标识符名称可能包含字母数字字符和下划线字符(_)。
以下列表显示了Ruby中的保留字。这些保留字不能用作常量或变量名。但是,它们可以用作方法名称。
开始 | do | 下一个 | 然后 |
结束 | other | 零 | 真正 |
别名 | 埃尔斯夫 | 不 | undef |
&& | 结束 | || | 除非 |
开始 | 确保 | 重做 | 直到 |
break | false | 拯救 | 什么时候 |
案件 | 对于 | 重试 | 而 |
class | 如果 | return | 而 |
def | 在 | 自 | __文件__ |
定义? | 模块 | 超 | __线__ |
“这里的文档”是指从多行创建字符string。遵循<<您可以指定一个字符string或标识符来终止字符string文字,并且当前行之后的所有行都是字符string的值。
如果引用了终止符,则引号类型决定了面向行的字符string文字的类型。注意<<和终止符之间不能有空格。
这里有不同的例子 -
#!/usr/bin/ruby -w print <<EOF This is the first way of creating here document ie. multiple line string. EOF print <<"EOF"; # same as above This is the second way of creating here document ie. multiple line string. EOF print <<`EOC` # execute commands echo hi there echo lo there EOC print <<"foo", <<"bar" # you can stack them I said foo. foo I said bar. bar
输出结果如下 -
This is the first way of creating her document ie. multiple line string. This is the second way of creating her document ie. multiple line string. hi there lo there I said foo. I said bar.
BEGIN { code }
声明在程序运行之前要调用的代码。
#!/usr/bin/ruby puts "This is main Ruby Program" BEGIN { puts "Initializing Ruby Program" }
输出结果如下 -
Initializing Ruby Program This is main Ruby Program
END { code }
声明在程序结束时调用的代码。
#!/usr/bin/ruby puts "This is main Ruby Program" END { puts "Terminating Ruby Program" } BEGIN { puts "Initializing Ruby Program" }
输出结果如下 -
Initializing Ruby Program This is main Ruby Program Terminating Ruby Program
一个注释隐藏了一行,一行的一部分,或者是Ruby解释器的几行。您可以使用行的开头的哈希字符(#)
# I am a comment. Just ignore me.
或者,在声明或表达之后,注释可能在同一行上 -
name = "Madisetti" # This is again comment
您可以如下注释多行:
# This is a comment. # This is a comment, too. # This is a comment, too. # I said that already.
这是另一种形式。这个块注释从解释器中隐藏了几行,其中= begin / = end -
= begin This is a comment. This is a comment, too. This is a comment, too. I said that already. = end
Ruby是一个完美的面向对象编程语言。面向对象编程语言的特点包括 -
这些特性已经在面向对象Ruby的一章中探讨过了。
面向对象的程序涉及类和对象。类是创建单个对象的蓝图。在面向对象的术语中,我们说你的自行车是被称为自行车的物体的一个实例。
以任何车辆为例。它包括轮子,马力,燃料或燃气罐容量。这些特征形成了车辆类的数据成员。借助这些特点,您可以区分一辆车与另一辆。
车辆还可以具有某些功能,例如停止,驾驶和加速。即使这些功能也构成了Vehicle类的数据成员。因此,您可以将类定义为特征和功能的组合。
一类车可以定义为 -
Class Vehicle { Number no_of_wheels Number horsepower Characters type_of_tank Number Capacity Function speeding { } Function driving { } Function halting { } }
通过为这些数据成员分配不同的值,您可以形成类Vehicle的几个实例。例如,一架飞机有三个轮子,马力为1,000,燃料为坦克类型,容量为100升。同样的方式,一辆汽车有四个轮子,二十马力,燃气作为坦克的类型,容量为25升。
要通过使用Ruby实现面向对象的编程,您需要首先学习如何在Ruby中创建对象和类。
Ruby中的类始终以关键字类和类的名称开头。这个名字应该始终是在首都的首都。课程客户可以显示为 -
class Customer end
您可以使用关键字结束终止类。类中的所有数据成员都在类定义和结束关键字之间。
Ruby提供了四种类型的变量 -
局部变量 - 局部变量是方法中定义的变量。局部变量在方法之外是不可用的。您将在后续章节中看到关于方法的更多细节。局部变量以小写字母或_开头。
实例变量 - 实例变量可用于任何特定实例或对象的方法。这意味着实例变量从对象变化。实例变量前面带有at符号(@),后跟变量名称。
类变量 - 类变量可用于不同的对象。类变量属于类,是类的特征。它们之前带有@@,后跟变量名。
全局变量 - 类变量在类之间不可用。如果你想要有一个单独的变量,这个变量可以跨类来使用,你需要定义一个全局变量。全局变量始终位于美元符号($)之前。
使用类变量@@ no_of_customers,可以确定正在创建的对象数。这样可以获得客户数量。
class Customer @@no_of_customers = 0 end
对象是类的实例。现在您将学习如何在Ruby中创建类的对象。您可以通过使用新的类的方法在Ruby中创建对象。
方法new是一种独特的方法,它是在Ruby库中预定义的。新方法属于类方法。
以下是创建Customer类的两个对象cust1和cust2的示例:
cust1 = Customer. new cust2 = Customer. new
在这里,cust1和cust2是两个对象的名称。您写的对象名称后跟等号(=),之后类名将跟随。然后,点运算符和关键字new将跟随。
您可以将参数传递给方法new,这些参数可用于初始化类变量。
当您计划使用参数声明新方法时,需要在创建类时声明方法initialize。
初始化方法是一种特殊类型的方法中,当将要执行的新的类的方法被调用的参数。
以下是创建initialize方法的示例 -
class Customer @@no_of_customers = 0 def initialize(id, name, addr) @cust_id = id @cust_name = name @cust_addr = addr end end
在这个例子中,你使用id,name和addr来声明initialize方法作为局部变量。这里,def和end用于定义Ruby方法初始化。您将在后续章节中更多地了解方法。
在初始化方法中,将这些局部变量的值传递给实例变量@cust_id,@cust_name和@cust_addr。这里局部变量包含与新方法一起传递的值。
现在,您可以创建如下对象 -
cust1 = Customer.new("1", "John", "Wisdom Apartments, Ludhiya") cust2 = Customer.new("2", "Poul", "New Empire road, Khandala")
在Ruby中,函数称为方法。类中的每个方法都以关键字def开头,后跟方法名称。
方法名称始终以小写字母表示。您可以使用关键字end在Ruby中结束一个方法。
以下是定义Ruby方法的示例 -
class Sample def function statement 1 statement 2 end end
这里,语句1和语句2是类Sample内部方法函数的一部分。这些数据可以是任何有效的Ruby语句。例如,我们可以把方法放在打印你好红宝石如下-
class Sample def hello puts "Hello Ruby!" end end
现在在下面的例子中,创建一个Sample类的对象并调用hello方法并查看结果 -
#!/usr/bin/ruby class Sample def hello puts "Hello Ruby!" end end # Now using above class to create objects object = Sample. new object.hello
输出结果如下 -
Hello Ruby!
这是一个案例研究,如果你想做更多的练习与类和对象。
变量是存储器位置,它保存任何程序要使用的数据。
Ruby支持的变体有五种类型。您也已经在上一章中简要介绍了这些变量。本章介绍了这五种类型的变量。
全局变量以$开头。未初始化的全局变量的值为nil,并使用-w选项生成警告。
赋予全局变量改变全局状态。不建议使用全局变量。他们使程序隐藏。
下面是一个示例,显示全局变量的用法。
#!/usr/bin/ruby $global_variable = 10 class Class1 def print_global puts "Global variable in Class1 is #$global_variable" end end class Class2 def print_global puts "Global variable in Class2 is #$global_variable" end end class1obj = Class1.new class1obj.print_global class2obj = Class2.new class2obj.print_global
这里$ global_variable是一个全局变量。输出结果如下 -
注意 - 在Ruby中,您可以通过在该变量或常量之前放置一个哈希(#)字符来访问任何变量或常量的值。
Global variable in Class1 is 10 Global variable in Class2 is 10
实例变量以@开头。未初始化的实例变量的值为nil,并使用-w选项生成警告。
下面是一个示例,显示实例变量的用法。
#!/usr/bin/ruby class Customer def initialize(id, name, addr) @cust_id = id @cust_name = name @cust_addr = addr end def display_details() puts "Customer id #@cust_id" puts "Customer name #@cust_name" puts "Customer address #@cust_addr" end end # Create Objects cust1 = Customer.new("1", "John", "Wisdom Apartments, Ludhiya") cust2 = Customer.new("2", "Poul", "New Empire road, Khandala") # Call Methods cust1.display_details() cust2.display_details()
这里,@cust_id,@cust_name和@cust_addr是实例变量。输出结果如下 -
Customer id 1 Customer name John Customer address Wisdom Apartments, Ludhiya Customer id 2 Customer name Poul Customer address New Empire road, Khandala
类变量以@@开始,并且必须先进行初始化,然后才能在方法定义中使用。
引用未初始化的类变量会产生错误。类变量在定义类变量的类或模块的后代中共享。
覆盖类变量使用-w选项生成警告。
下面是一个示例,显示了类变量的用法 -
#!/usr/bin/ruby class Customer @@no_of_customers = 0 def initialize(id, name, addr) @cust_id = id @cust_name = name @cust_addr = addr end def display_details() puts "Customer id #@cust_id" puts "Customer name #@cust_name" puts "Customer address #@cust_addr" end def total_no_of_customers() @@no_of_customers += 1 puts "Total number of customers: #@@no_of_customers" end end # Create Objects cust1 = Customer.new("1", "John", "Wisdom Apartments, Ludhiya") cust2 = Customer.new("2", "Poul", "New Empire road, Khandala") # Call Methods cust1.total_no_of_customers() cust2.total_no_of_customers()
这里@@ no_of_customers是一个类变量。输出结果如下 -
Total number of customers: 1 Total number of customers: 2
局部变量以小写字母或_开头。局部变量的范围从class,module,def或do到相应的end或从块的开放大括号到其关闭大括号{}。
当引用未初始化的局部变量时,它被解释为对没有参数的方法的调用。
对未初始化的局部变量的分配也用作变量声明。变量开始存在,直到达到当前作用域的结尾。当Ruby解析程序时,确定局部变量的生命周期。
在上面的例子中,局部变量是id,name和addr。
常数以大写字母开头。在类或模块中定义的常量可以从该类或模块中访问,并且可以全局访问在类或模块外部定义的常量。
方法中可能不会定义常量。引用未初始化的常量会产生错误。对已经初始化的常量进行分配会产生警告。
#!/usr/bin/ruby class Example VAR1 = 100 VAR2 = 200 def show puts "Value of first Constant is #{VAR1}" puts "Value of second Constant is #{VAR2}" end end # Create Objects object = Example.new() object.show
这里VAR1和VAR2是常数。输出结果如下 -
Value of first Constant is 100 Value of second Constant is 200
它们是具有局部变量的外观的特殊变量,但是它的行为就像常量。您不能为这些变量分配任何值。
self - 当前方法的接收者对象。
true - 值表示true。
false - 表示false的值。
无 - 表示未定义的值。
__FILE__ - 当前源文件的名称。
__LINE__ - 源文件中的当前行号。
Ruby用于文字的规则是简单直观的。本节将介绍所有基本的Ruby Literals。
Ruby支持整数。的整数的范围可以从-2 30到2 30-1或-2 62到2 62-1。在此范围内的整数是Fixnum类的对象,并且此范围之外的整数存储在Bignum类的对象中。
您可以使用可选的前导符号,可选的基本指示符(0表示八进制,0x表示十六进制,或0b代表二进制)写入整数,后跟相应基数字符string。下划线字符在数字字符string中被忽略。
您还可以获取与ASCII字符相对应的整数值,或者通过使用问号来排除序列。
123 # Fixnum decimal 1_234 # Fixnum decimal with underline -500 # Negative Fixnum 0377 # octal 0xff # hexadecimal 0b1011 # binary ?a # character code for "a" ? # code for a newline (0x0a) 12345678901234567890 # Bignum
注 - 类和对象在本教程的另一章中进行了说明。
Ruby支持整数。他们也是数字,但是小数位。浮点数是Float类的对象,可以是以下任何一个 -
123.4 # floating point value 1.0e6 # scientific notation 4E20 # dot not required 4e+20 # sign before exponential
Ruby字符string是8位字节的简单序列,它们是String类的对象。双引号字符string允许替换和反斜杠符号,但单引号字符string不允许替换,并允许仅对和"进行反斜杠符号
#!/usr/bin/ruby -w puts "escape using """; puts "That"s right";
输出结果如下 -
escape using "" That"s right
您可以使用序列#{expr}将任何Ruby表达式的值替换为字符string。在这里,expr可以是任何ruby表达式。
#!/usr/bin/ruby -w puts "Multiplication Value : #{24*60*60}";
输出结果如下 -
Multiplication Value : 86400
以下是Ruby支持的反斜杠符号列表 -
符号 | 字符代表 |
---|---|
n | 换行(0x0a) |
r | 回车(0x0d) |
F | Formfeed(0x0c) |
b | 退格(0x08) |
一个 | 贝尔(0x07) |
e | 逃脱(0x1b) |
s | 空格(0x20) |
nnn | 八进制符号(n为0-7) |
xnn | 十六进制符号(n为0-9,af或AF) |
cx, Cx | Control-x |
Mx | Meta-x(c | 0x80) |
M- Cx | 元控制x |
X | 字符x |
有关Ruby字符string的更多详细信息,请访问Ruby字符string。
Ruby Array的文字通过在方括号之间放置逗号分隔的一系列对象引用来创建。后面的逗号被忽略。
#!/usr/bin/ruby ary = [ "fred", 10, 3.14, "This is a string", "last element", ] ary.each do |i| puts i end
输出结果如下 -
fred 10 3.14 This is a string last element
有关Ruby数组的更多详细信息,请访问Ruby数组。
一个文字的Ruby哈希是通过在一个大括号之间放置一个键/值对的列表来创建的,逗号或键和值之间的序列=>。后面的逗号被忽略。
#!/usr/bin/ruby hsh = colors = { "red" => 0xf00, "green" => 0x0f0, "blue" => 0x00f } hsh.each do |key, value| print key, " is ", value, " " end
输出结果如下 -
red is 3840 green is 240 blue is 15
有关Ruby Hash的更多细节,请浏览Ruby Hash。
一个范围代表一个间隔。一组开始和结束的值。可以使用s..e和s ... e文字或Range.new创建范围。
使用..从开始到结束运行的范围包括。使用...创建的排除结束值。当用作迭代器时,范围返回序列中的每个值。
范围(1..5)表示包括1,2,3,4,5值,范围(1 ... 5)表示包括1,2,3,4值。
#!/usr/bin/ruby (10..15).each do |n| print n, " " end
输出结果如下 -
10 11 12 13 14 15
有关Ruby Ranges的更多详细信息,请访问Ruby Ranges。
Ruby支持一组丰富的运算符,就像您所期望的一种现代语言一样。大多数运算符实际上是方法调用。例如,a + b被解释为一个+(b),其中变量a引用的对象中的+方法以b为参数来调用。
对于每个运算符(+ - * /%**&| ^ << >> && ||),有一个相应的缩写赋值运算符(+ = - =等)。
假设变量a保持10,变量b保持20,则 -
没有 | 操作符和说明 | 例 |
---|---|---|
1 | +
加法 - 在运算符的两边添加值。 |
a + b将给予30 |
2 | -
减法 - 从左手操作数减去右手操作数。 |
a - b会给-10 |
3 | *
乘法 - 在运算符的两边乘以值。 |
a * b会给予200 |
4 | /
部门 - 用右手操纵数除数左手操作数。 |
b / a将给予2 |
5 | %
模数 - 用右手操作数除左手操作数并返回余数。 |
b%a会给0 |
6 | **
指数 - 对运算符执行指数(幂)计算。 |
a ** b将给予权力20 |
假设变量a保持10,变量b保持20,则 -
没有 | 操作符和说明 | 例 |
---|---|---|
1 | ==
检查两个操作数的值是否相等,如果是,则条件成立。 |
(a == b)不正确。 |
2 | !=
检查两个操作数的值是否相等,如果值不等于条件成立。 |
(a!= b)是真的。 |
3 | >
检查左操作数的值是否大于右操作数的值,如果是,则条件成为真。 |
(a> b)不正确。 |
4 | <
检查左操作数的值是否小于右操作数的值,如果是,则条件成为真。 |
(a <b)是真的。 |
5 | > =
检查左操作数的值是否大于或等于右操作数的值,如果是,则条件成为真。 |
(a> = b)不是真的。 |
6 | <=
检查左操作数的值是否小于或等于右操作数的值,如果是,则条件成为真。 |
(a <= b)是真的。 |
7 | <=>
组合比较运算符。如果第一个操作数等于秒,则返回0,如果第一个操作数大于第二个,则返回1,如果第一个操作数小于第二个则返回-1。 |
(a <=> b)返回-1。 |
8 | ===
用于测试case语句的when子句中的相等性。 |
(1 ... 10)=== 5返回true。 |
9 | .eql?
如果接收者和参数具有相同的类型和相等的值,则为真。 |
1 == 1.0返回true,但是1.eql?(1.0)是false。 |
10 | 等于?
如果接收方和参数具有相同的对象标识,则为真。 |
如果aObj与bObj重复,那么aObj == bObj为true,则a.equal?bObj为false,但a.equal?aObj为true。 |
假设变量a保持10,变量b保持20,则 -
没有 | 操作符和说明 | 例 |
---|---|---|
1 | =
简单赋值运算符,将右侧操作数的值分配给左侧操作数。 |
c = a + b将a + b的值分配给c |
2 | + =
添加AND赋值运算符,将右操作数添加到左操作数,并将结果分配给左操作数。 |
c + = a等价于c = c + a |
3 | - =
减去AND赋值运算符,从左操作数中减去右操作数,并将结果分配给左操作数。 |
c * - = a等价于c = c - a |
4 | * =
乘以AND赋值运算符,将右操作数与左操作数相乘,并将结果分配给左操作数。 |
c * = a等价于c = c * a |
5 | / =
除以AND赋值运算符,将左操作数与右操作数分开,并将结果分配给左操作数。 |
c / = a等价于c = c / a |
6 | %=
模数AND分配运算符,使用两个操作数来计算模数,并将结果分配给左操作数。 |
c%= a等价于c = c%a |
7 | ** =
指数AND赋值运算符对运算符进行指数(幂)运算,并将值分配给左操作数。 |
c ** = a等价于c = c ** a |
Ruby还支持并行分配变量。这样可以使用一行Ruby代码初始化多个变量。例如 -
a = 10 b = 20 c = 30
这可能会使用并行分配更快地声明 -
a, b, c = 10, 20, 30
并行分配对于交换保存在两个变量中的值也是有用的 -
a, b = b, c
按位运算符对位执行,并进行逐位运算。
假设a = 60; 和b = 13; 现在以二进制格式,他们将如下 -
a = 0011 1100 b = 0000 1101 ------------------ a&b = 0000 1100 a|b = 0011 1101 a^b = 0011 0001 ~a = 1100 0011
Ruby语言支持以下Bitwise运算符。
没有 | 操作符和说明 | 例 |
---|---|---|
1 | &
如果二进制AND运算符存在于两个操作数中,则二进制AND运算符将对结果复制一位。 |
(a&b)将给予12,即0000 1100 |
2 | |
二进制OR运算符如果存在于任一操作数中,则复制一位。 |
(a | b)将给出61,即0011 1101 |
3 | ^
二进制XOR操作符复制该位,如果它设置在一个操作数中,而不是两者。 |
(a ^ b)将给出49,即0011 0001 |
4 | 〜
二进制补码运算符是一元的,具有“翻转”位的作用。 |
(〜a)将给出-61,由于符号二进制数,其为2的补码形式为1100 0011。 |
5 | <<
二进制左移操作符。左操作数值左移由右操作数指定的位数。 |
一个<< 2将给予240,即1111 0000 |
6 | >>
二进制右移操作符。左操作数值被右操作数指定的位移动。 |
a >> 2将给出15,这是0000 1111 |
Ruby语言支持以下逻辑运算符
假设变量a保持10,变量b保持20,则 -
没有 | 操作符和说明 | 例 |
---|---|---|
1 | 和
称为逻辑AND运算符。如果两个操作数都为真,则条件成立。 |
(a和b)是真的。 |
2 | 或
称为逻辑或运算符。如果两个操作数中的任何一个为非零,则条件成立。 |
(a或b)是真的。 |
3 | &&
称为逻辑AND运算符。如果两个操作数都不为零,则条件成立。 |
(a && b)是真的。 |
4 | ||
称为逻辑或运算符。如果两个操作数中的任何一个为非零,则条件成立。 |
(a || b)为真。 |
5 | !
称为逻辑非运算符。用于反转其操作数的逻辑状态。如果条件为真,则逻辑NOT运算符将为false。 |
!(a && b)是假的。 |
6 | 不
称为逻辑非运算符。用于反转其操作数的逻辑状态。如果条件为真,则逻辑NOT运算符将为false。 |
不(a && b)是假的。 |
还有一个叫三元运算符的运算符。它首先计算一个表达式的true或false值,然后根据评估结果执行两个给定语句之一。条件运算符具有这种语法 -
没有 | 操作符和说明 | 例 |
---|---|---|
1 | ?:
条件表达式 |
如果条件是真的?那么值X:否则值Y |
Ruby中的序列范围用于创建一系列连续的值 - 由起始值,结束值和值之间的范围组成。
在Ruby中,这些序列使用“..”和“...”范围运算符创建。双点格式创建一个包含范围,而三点形式创建一个排除指定高值的范围。
没有 | 操作符和说明 | 例 |
---|---|---|
1 | .. ..
创建从起点到终点的范围。 |
1..10创建范围从1到10(含)。 |
2 | ...
创建从起始点到终点独占的范围。 |
1 ... 10创建范围从1到9。 |
定义?是一个特殊的操作符,采用方法调用的形式来确定传递的表达式是否被定义。它返回表达式的描述字符string,如果表达式未定义,则返回nil。
有各种用法定义?操作符
defined? variable # True if variable is initialized
例如
foo = 42 defined? foo # => "local-variable" defined? $_ # => "global-variable" defined? bar # => nil (undefined)
defined? method_call # True if a method is defined
例如
defined? puts # => "method" defined? puts(bar) # => nil (bar is not defined here) defined? unpack # => nil (not defined here)
# True if a method exists that can be called with super user defined? super
例如
defined? super # => "super" (if it can be called) defined? super # => nil (if it cannot be)
defined? yield # True if a code block has been passed
例如
defined? yield # => "yield" (if there is a block passed) defined? yield # => nil (if there is no block)
您可以通过使用模块名称和句点名称来调用模块方法,并使用模块名称和两个冒号引用常量。
的::是一元运算符,其允许:一个类或模块中定义的常量,实例方法和类方法中,待从类或模块以外的任何地方访问。
记住在Ruby中,类和方法也可以被认为是常量。
您需要在:: Const_name前面加上一个返回相应类或模块对象的表达式。
如果不使用前缀表达式,则默认使用主Object类。
这里有两个例子 -
MR_COUNT = 0 # constant defined on main Object class module Foo MR_COUNT = 0 ::MR_COUNT = 1 # set global count to 1 MR_COUNT = 2 # set local count to 2 end puts MR_COUNT # this is the global constant puts Foo::MR_COUNT # this is the local "Foo" constant
第二个例子
CONST = " out there" class Inside_one CONST = proc {" in there"} def where_is_my_CONST ::CONST + " inside one" end end class Inside_two CONST = " inside two" def where_is_my_CONST CONST end end puts Inside_one.new.where_is_my_CONST puts Inside_two.new.where_is_my_CONST puts Object::CONST + Inside_two::CONST puts Inside_two::CONST + CONST puts Inside_one::CONST puts Inside_one::CONST.call + Inside_two::CONST
下表列出了从最高优先级到最低优先级的所有运算符。
方法 | 操作符 | 描述 |
---|---|---|
是 | :: | 恒定分辨率算子 |
是 | [] [] = | 元素参考,元素集 |
是 | ** | 指数(提高权力) |
是 | !〜+ - | 不,补,一元加减(最后两个的方法名称是+ @和 - @) |
是 | * /% | 乘,除和模 |
是 | + - | 加减 |
是 | >> << | 左右向右移位 |
是 | & | 按位“AND” |
是 | ^ | | 按位异或“OR”和常规的“OR” |
是 | <= <>> = | 比较运算符 |
是 | <=> == ===!= =〜!〜 | 平等和模式匹配运算符(!=和!〜可能不被定义为方法) |
&& | 逻辑"AND" | |
|| | 逻辑"OR" | |
.. ... | 范围(包括和排他性) | |
?: | 三元如果 - 否则 | |
=%= {/ = - = + = | =&= >> = << = * = && = || = ** = | 分配 | |
定义? | 检查指定的符号是否定义 | |
不 | 逻辑否定 | |
或者 | 逻辑构成 |
注 - 方法列中有“是 ”的运算符实际上是方法,因此可能会被覆盖。
注释是Ruby代码中的注释行,在运行时被忽略。单行注释以#个字符开头,它们从#延伸到行尾,如下所示:
#!/usr/bin/ruby -w # This is a single line comment. puts "Hello, Ruby!"
执行时,上述程序产生以下结果 -
Hello, Ruby!
您可以使用= begin和= end语法来注释多行,如下所示:
#!/usr/bin/ruby -w puts "Hello, Ruby!" =begin This is a multiline comment and con spwan as many lines as you like. But =begin and =end should come in the first line only. =end
执行时,上述程序产生以下结果 -
Hello, Ruby!
确保尾随注释远离代码,并且易于区分。如果块中存在多个尾随注释,请对齐它们。例如 -
@counter # keeps track times page has been hit @siteCounter # keeps track of times all pages have been hit
Ruby提供了现代语言很常见的条件结构。在这里,我们将解释Ruby中可用的所有条件语句和修饰符。
if conditional [then] code... [elsif conditional [then] code...]... [else code...] end
如果表达式用于条件执行。值false和nil是false,其他的都是true。注意Ruby使用elsif,而不是if elifif。
如果条件为真,则执行代码。如果条件不为真,则执行else子句中指定的代码。
如果一个表达式的条件从由代码保留字分离然后,换行,或分号。
#!/usr/bin/ruby x = 1 if x > 2 puts "x is greater than 2" elsif x <= 2 and x!=0 puts "x is 1" else puts "I can"t guess the number" end
x is 1
code if condition
如果条件为真,则执行代码。
#!/usr/bin/ruby $debug = 1 print "debug " if $debug
输出结果如下 -
debug
unless conditional [then] code [else code ] end
如果条件为false,则执行代码。如果条件为true,则执行else子句中指定的代码。
#!/usr/bin/ruby x = 1 unless x>2 puts "x is less than 2" else puts "x is greater than 2" end
输出结果如下 -
x is less than 2
code unless conditional
如果条件为false,则执行代码。
#!/usr/bin/ruby $var = 1 print "1 -- Value is set " if $var print "2 -- Value is set " unless $var $var = false print "3 -- Value is set " unless $var
输出结果如下 -
1 -- Value is set 3 -- Value is set
case expression [when expression [, expression ...] [then] code ]... [else code ] end
比较由case指定的表达式和使用===运算符时指定的表达式,并执行与之匹配的when子句的代码。
的表达由当子句指定被评价为左操作数。如果no子句匹配,则case会执行else子句的代码。
阿当语句的表达是从代码由保留字然后,换行,或分号隔开。因此 -
case expr0 when expr1, expr2 stmt1 when expr3, expr4 stmt2 else stmt3 end
基本上类似于以下 -
_tmp = expr0 if expr1 === _tmp || expr2 === _tmp stmt1 elsif expr3 === _tmp || expr4 === _tmp stmt2 else stmt3 end
#!/usr/bin/ruby $age = 5 case $age when 0 .. 2 puts "baby" when 3 .. 6 puts "little child" when 7 .. 12 puts "child" when 13 .. 18 puts "youth" else puts "adult" end
输出结果如下 -
little child
Ruby中的循环用于执行相同的代码块指定次数。本章详细介绍了Ruby支持的所有循环语句。
while conditional [do] code end
执行代码,而条件是真实的。甲而循环的条件是从分离代码由保留字做,换行,反斜线或分号。
#!/usr/bin/ruby $i = 0 $num = 5 while $i < $num do puts("Inside the loop i = #$i" ) $i +=1 end
输出结果如下 -
Inside the loop i = 0 Inside the loop i = 1 Inside the loop i = 2 Inside the loop i = 3 Inside the loop i = 4
code while condition OR begin code end while conditional
执行代码,而条件是真实的。
如果while修饰符遵循没有拯救或确认子句的begin语句,则在对条件进行求值之前执行代码。
#!/usr/bin/ruby $i = 0 $num = 5 begin puts("Inside the loop i = #$i" ) $i +=1 end while $i < $num
输出结果如下 -
Inside the loop i = 0 Inside the loop i = 1 Inside the loop i = 2 Inside the loop i = 3 Inside the loop i = 4
until conditional [do] code end
执行代码,而条件是假的。一到语句的条件是分开的代码被保留字做,换行或分号。
#!/usr/bin/ruby $i = 0 $num = 5 until $i > $num do puts("Inside the loop i = #$i" ) $i +=1; end
输出结果如下 -
Inside the loop i = 0 Inside the loop i = 1 Inside the loop i = 2 Inside the loop i = 3 Inside the loop i = 4 Inside the loop i = 5
code until conditional OR begin code end until conditional
执行代码,而条件是假的。
如果直到修饰符遵循没有拯救或确认子句的begin语句,则在评估条件之前执行代码一次。
#!/usr/bin/ruby $i = 0 $num = 5 begin puts("Inside the loop i = #$i" ) $i +=1; end until $i > $num
输出结果如下 -
Inside the loop i = 0 Inside the loop i = 1 Inside the loop i = 2 Inside the loop i = 3 Inside the loop i = 4 Inside the loop i = 5
for variable [, variable ...] in expression [do] code end
对表达式中的每个元素执行一次代码。
#!/usr/bin/ruby for i in 0..5 puts "Value of local variable is #{i}" end
在这里,我们定义了范围0..5。我在0..5中的声明将允许我从0到5(包括5)范围内的值。输出结果如下 -
Value of local variable is 0 Value of local variable is 1 Value of local variable is 2 Value of local variable is 3 Value of local variable is 4 Value of local variable is 5
A for ... in循环几乎完全相当于以下 -
(expression).each do |variable[, variable...]| code end
除了for循环不会为局部变量创建新的范围。甲用于循环的表达从分离代码由保留字做,一个新行,或分号。
#!/usr/bin/ruby (0..5).each do |i| puts "Value of local variable is #{i}" end
输出结果如下 -
Value of local variable is 0 Value of local variable is 1 Value of local variable is 2 Value of local variable is 3 Value of local variable is 4 Value of local variable is 5
break
终止最内部的循环。如果在块内调用(终止方法返回nil),则终止具有关联块的方法。
#!/usr/bin/ruby for i in 0..5 if i > 2 then break end puts "Value of local variable is #{i}" end
输出结果如下 -
Value of local variable is 0 Value of local variable is 1 Value of local variable is 2
next
跳转到最内部循环的下一个迭代。如果在块内调用(终止收益或调用返回零),则终止块的执行。
#!/usr/bin/ruby for i in 0..5 if i < 2 then next end puts "Value of local variable is #{i}" end
输出结果如下 -
Value of local variable is 2 Value of local variable is 3 Value of local variable is 4 Value of local variable is 5
redo
重新启动最内部循环的此迭代,而不检查循环条件。如果在块内调用,重新启动产量或调用。
#!/usr/bin/ruby for i in 0..5 if i < 2 then puts "Value of local variable is #{i}" redo end end
输出结果如下,并将进入无限循环 -
Value of local variable is 0 Value of local variable is 0 ............................
retry
如果retry出现在begin表达式的rescue子句中,请从begin body的开头重新启动。
begin do_something # exception raised rescue # handles error retry # restart from beginning end
如果重试出现在迭代器中,块或for表达式的正文将重新启动迭代器调用。迭代器的参数被重新评估。
for i in 1..5 retry if some_condition # restart from i == 1 end
#!/usr/bin/ruby for i in 0..5 if i > 2 puts "Value of local variable is #{i}" end
输出结果如下,并将进入无限循环 -
Value of local variable is 1 Value of local variable is 2 Value of local variable is 1 Value of local variable is 2 Value of local variable is 1 Value of local variable is 2 ............................
Ruby方法与任何其他编程语言中的函数非常相似。Ruby方法用于将一个或多个可重复语句捆绑到一个单元中。
方法名称应以小写字母开头。如果您开始使用大写字母的方法名称,Ruby可能会认为它是一个常量,因此可能会错误地解析该调用。
在调用它们之前应该定义方法,否则Ruby会为未定义的方法调用引发异常。
def method_name [( [arg [= default]]...[, * arg [, &expr ]])] expr.. end
所以,你可以定义一个简单的方法如下 -
def method_name expr.. end
你可以表示一个接受这样的参数的方法 -
def method_name (var1, var2) expr.. end
您可以为参数设置默认值,如果调用方法而不传递必需的参数,则将使用该值。
def method_name (var1 = value1, var2 = value2) expr.. end
每当调用简单的方法时,只写下方法名称,如下所示:
method_name
但是,当您使用参数调用方法时,可以将方法名称与参数一起编写,例如 -
method_name 25, 30
使用参数的方法最重要的缺点是每当您调用这些方法时,都需要记住参数的数量。例如,如果一个方法接受三个参数,只传递两个参数,那么Ruby会显示错误。
#!/usr/bin/ruby def test(a1 = "Ruby", a2 = "Perl") puts "The programming language is #{a1}" puts "The programming language is #{a2}" end test "C", "C++" test
输出结果如下 -
The programming language is C The programming language is C++ The programming language is Ruby The programming language is Perl
默认情况下,Ruby中的每个方法都返回一个值。这个返回的值将是最后一个语句的值。例如 -
def test i = 100 j = 10 k = 0 end
该方法在被调用时将返回最后声明的变量k。
ruby中的return语句用于从Ruby方法返回一个或多个值。
return [expr[`," expr...]]
如果给出两个以上的表达式,则包含这些值的数组将是返回值。如果没有给出表达式,nil将返回值。
return OR return 12 OR return 1,2,3
看看这个例子 -
#!/usr/bin/ruby def test i = 100 j = 200 k = 300 return i, j, k end var = test puts var
输出结果如下 -
100 200 300
假设你声明一个方法需要两个参数,每当你调用这个方法时,你需要传递两个参数。
但是,Ruby允许您声明使用可变数量参数的方法。让我们来看一下这个样本 -
#!/usr/bin/ruby def sample (*test) puts "The number of parameters is #{test.length}" for i in 0...test.length puts "The parameters are #{test[i]}" end end sample "Zara", "6", "F" sample "Mac", "36", "M", "MCA"
在这段代码中,您已经声明了一个接受一个参数测试的方法示例。但是,该参数是一个可变参数。这意味着该参数可以占用任意数量的变量。所以,上面的代码将产生以下结果 -
The number of parameters is 3 The parameters are Zara The parameters are 6 The parameters are F The number of parameters is 4 The parameters are Mac The parameters are 36 The parameters are M The parameters are MCA
当方法在类定义之外定义时,默认情况下该方法被标记为private。另一方面,默认情况下,类定义中定义的方法被标记为public。模块的默认可见性和私有标记可以通过模块的公开或私有更改。
每当你想访问一个类的方法,你首先需要实例化类。然后,使用该对象,您可以访问该类的任何成员。
Ruby给你一种方法来访问一个方法而不实例化一个类。让我们看看如何声明和访问类方法 -
class Accounts def reading_charge end def Accounts.return_date end end
查看方法return_date如何声明。它以类名声明,后跟一个句点,后跟方法的名称。您可以直接访问此类方法,如下所示:
Accounts.return_date
要访问此方法,您不需要创建类帐户的对象。
这给了方法或全局变量的别名。别名不能在方法体内定义。该方法的别名保持当前方法的定义,即使方法被覆盖。
为编号的全局变量($ 1,$ 2,...)创建别名是禁止的。覆盖内置的全局变量可能会导致严重的问题。
alias method-name method-name alias global-variable-name global-variable-name
alias foo bar alias $MATCH $&
这里我们为bar定义了foo别名,$ MATCH是$&
这取消了方法定义。一个民主基金不能出现在方法体中。
通过使用undef和别名,类的接口可以独立于超类进行修改,但注意可能会通过内部方法调用self来破坏程序。
undef method-name
要定义一个名为bar的方法,请执行以下操作:
undef bar
您已经看到Ruby如何定义方法,您可以在其中放置数量的语句,然后调用该方法。类似地,Ruby有一个Block的概念。
一个块由大量的代码组成。
您为块指定名称。
块中的代码始终包含在大括号({})中。
总是从与块的名称相同的函数调用块。这意味着如果您有一个具有名称测试的块,则使用函数test调用此块。
您使用yield语句调用块。
block_name{ statement1 statement2 .......... }
在这里,您将学习通过使用简单的yield语句来调用块。您还将学习使用带有参数的yield语句来调用块。您将使用两种类型的yield语句来检查示例代码。
我们来看看yield语句的一个例子 -
#!/usr/bin/ruby def test puts "You are in the method" yield puts "You are again back to the method" yield end test {puts "You are in the block"}
输出结果如下 -
You are in the method You are in the block You are again back to the method You are in the block
您还可以使用yield语句传递参数。这是一个例子 -
#!/usr/bin/ruby def test yield 5 puts "You are in the method test" yield 100 end test {|i| puts "You are in the block #{i}"}
输出结果如下 -
You are in the block 5 You are in the method test You are in the block 100
这里,yield语句被写入后跟参数。甚至可以传递多个参数。在块中,您可以在两条垂直线(||)之间放置一个变量来接受参数。因此,在上述代码中,yield 5语句将值5作为参数传递给测试块。
现在,看下面的语句 -
test {|i| puts "You are in the block #{i}"}
这里,在变量i中接收值5 。现在,请遵守以下放声明-
puts "You are in the block #{i}"
这个put语句的输出是 -
You are in the block 5
如果要传递多个参数,则yield语句将变为 -
yield a, b
和块是 -
test {|a, b| statement}
参数将以逗号分隔。
您已经看到块和方法可以如何相互关联。通常使用来自与块相同名称的方法的yield语句来调用块。所以你写 -
#!/usr/bin/ruby def test yield end test{ puts "Hello world"}
此示例是实现块的最简单方法。您可以使用yield语句调用测试块。
但是如果方法的最后一个参数前面加上&,那么可以将块传递给此方法,并将该块分配给最后一个参数。如果*和&都存在于参数列表中,则应该稍后再来。
#!/usr/bin/ruby def test(&block) block.call end test { puts "Hello World!"}
输出结果如下 -
Hello World!
每个Ruby源文件都可以在文件加载(BEGIN块)和程序完成执行(END块)后声明要运行的代码块。
#!/usr/bin/ruby BEGIN { # BEGIN block code puts "BEGIN code block" } END { # END block code puts "END code block" } # MAIN block code puts "MAIN code block"
程序可以包括多个BEGIN和END块。BEGIN块按照遇到的顺序执行。END块以相反的顺序执行。执行时,上述程序产生以下结果 -
BEGIN code block MAIN code block END code block
模块是一种将方法,类和常量分组在一起的方法。模块给您两大优势。
模块提供命名空间并防止名称冲突。
模块实现mixin设备。
模块定义一个命名空间,一个沙盒,您的方法和常量可以在其中播放,而无需担心被其他方法和常量所阻碍。
module Identifier statement1 statement2 ........... end
模块常量就像类常量一样被命名,带有一个初始的大写字母。方法定义也类似:模块方法就像类方法一样定义。
与类方法一样,您可以使用模块名称和句点名称来调用模块方法,并使用模块名称和两个冒号引用常量。
#!/usr/bin/ruby # Module defined in trig.rb file module Trig PI = 3.141592654 def Trig.sin(x) # .. end def Trig.cos(x) # .. end end
我们可以定义一个具有相同功能名称但功能不同的模块 -
#!/usr/bin/ruby # Module defined in moral.rb file module Moral VERY_BAD = 0 BAD = 1 def Moral.sin(badness) # ... end end
像类方法一样,只要在模块中定义方法,就可以指定模块名称后跟一个点,然后指定方法名称。
require语句类似于C和C ++的include语句以及Java的import语句。如果第三个程序想要使用任何定义的模块,它可以使用Ruby require语句简单地加载模块文件-
require filename
在这里,不需要给出.rb扩展名和文件名。
$LOAD_PATH << "." require "trig.rb" require "moral" y = Trig.sin(Trig::PI/4) wrongdoing = Moral.sin(Moral::VERY_BAD)
这里我们使用$ LOAD_PATH <<"。使Ruby意识到必须在当前目录中搜索包含的文件。如果不想使用$ LOAD_PATH,那么可以使用require_relative来包含相对目录中的文件。
重要 - 这里,这两个文件包含相同的函数名称。因此,这将导致代码模糊,同时包括在调用程序中,但模块避免了这种代码模糊,我们可以使用模块名称调用适当的函数。
你可以在一个类中嵌入一个模块。要在一个类中嵌入一个模块,你可以在类中使用include语句 -
include modulename
如果在单独的文件中定义了一个模块,则需要在将模块嵌入到类中之前使用require语句包含该文件。
考虑在support.rb文件中编写的以下模块。
module Week FIRST_DAY = "Sunday" def Week.weeks_in_month puts "You have four weeks in a month" end def Week.weeks_in_year puts "You have 52 weeks in a year" end end
现在,您可以将此模块包含在一个类中,如下所示:
#!/usr/bin/ruby $LOAD_PATH << "." require "support" class Decade include Week no_of_yrs = 10 def no_of_months puts Week::FIRST_DAY number = 10*12 puts number end end d1 = Decade.new puts Week::FIRST_DAY Week.weeks_in_month Week.weeks_in_year d1.no_of_months
输出结果如下 -
Sunday You have four weeks in a month You have 52 weeks in a year Sunday 120
在介绍本节之前,我们假设您具有面向对象概念的知识。
当一个类可以继承多个父类的特性时,该类应该显示多个继承。
Ruby不直接支持多重继承,但是Ruby模块有另外一个很好的用途。中间,他们几乎消除了对多重继承的需要,提供了一个名为mixin的工具。
Mixins为您提供了一种奇妙的控制方式,可以向类添加功能。然而,当mixin中的代码开始与使用它的类中的代码进行交互时,它们的真实Grav就出现了。
我们来看看下面的示例代码以了解mixin -
module A def a1 end def a2 end end module B def b1 end def b2 end end class Sample include A include B def s1 end end samp = Sample.new samp.a1 samp.a2 samp.b1 samp.b2 samp.s1
模块A由方法a1和a2组成。模块B由方法b1和b2组成。类Sample包含模块A和B。类Sample可以访问所有四种方法,即a1,a2,b1和b2。因此,您可以看到类Sample继承自两个模块。因此,您可以说类Sample显示多个继承或混合。
Ruby中的String对象持有并操纵一个或多个字节的任意序列,通常表示代表人类语言的字符。
最简单的字符string文字用单引号括起来(撇号字符)。引号内的文字是字符string的值 -
"This is a simple Ruby string literal"
如果您需要在单引号字符string中放置一个撇号,请在其前面加上反斜杠,以便Ruby解释器不认为它会终止字符string -
"Won"t you read O"Reilly"s book?"
反斜杠也可以转义另一个反斜杠,这样第二个反斜杠本身并不被解释为转义字符。
以下是Ruby的字符string相关功能。
表达式替换是使用#{和} - 将任何Ruby表达式的值嵌入到字符string中的一种手段 -
#!/usr/bin/ruby x, y, z = 12, 36, 72 puts "The value of x is #{ x }." puts "The sum of x and y is #{ x + y }." puts "The average was #{ (x + y + z)/3 }."
输出结果如下 -
The value of x is 12. The sum of x and y is 48. The average was 40.
使用一般分隔的字符string,您可以在一对匹配的任意分隔符字符中创建字符string,例如!,(,{,{等等,前面带有百分比字符(%)Q,q和x具有特殊含义一般分隔的字符string可以是 -
%{Ruby is fun.} equivalent to "Ruby is fun." %Q{ Ruby is fun. } equivalent to " Ruby is fun. " %q[Ruby is fun.] equivalent to a single-quoted string %x!ls! equivalent to back tick command output `ls`
Ruby的默认字符集是ASCII,其字符可以由单个字节表示。如果您使用UTF-8或其他现代字符集,则字符可能以一到四个字节表示。
您可以在程序开始时使用$ KCODE更改您的角色集,如下所示:
$KCODE = "u"
我们需要一个String对象的实例来调用String方法。以下是创建String对象实例的方法 -
new [String.new(str = "")]
这将返回一个包含str副本的新的字符string对象。现在,使用str对象,我们都可以使用任何可用的实例方法。例如 -
#!/usr/bin/ruby myStr = String.new("THIS IS TEST") foo = myStr.downcase puts "#{foo}"
输出结果如下 -
this is test
尝试以下示例来解压各种数据。
"abc abc ".unpack("A6Z6") #=> ["abc", "abc "] "abc ".unpack("a3a3") #=> ["abc", " 00 00"] "abc abc ".unpack("Z*Z*") #=> ["abc ", "abc "] "aa".unpack("b8B8") #=> ["10000110", "01100001"] "aaa".unpack("h2H2c") #=> ["16", "61", 97] "xfexffxfexff".unpack("sS") #=> [-2, 65534] "now = 20is".unpack("M*") #=> ["now is"] "whole".unpack("xax2aX2aX1aX2a") #=> ["h", "e", "l", "l", "o"]
Ruby数组是任何对象的有序整数索引集合。数组中的每个元素与索引相关联并由其引用。
数组索引从0开始,如C或Java。假定相对于数组的结尾为负的索引 - 也就是说,-1的索引表示数组的最后一个元素,-2是数组中最后一个元素的下一个,依此类推。
Ruby数组可以容纳诸如String,Integer,Fixnum,Hash,Symbol,甚至其他Array对象的对象。Ruby数组不像其他语言中的数组那么刚性。Ruby数组自动增加,同时向它们添加元素。
有许多方法可以创建或初始化数组。一种方法是使用新的类方法 -
names = Array.new
您可以在创建数组时设置数组的大小 -
names = Array.new(20)
数组名称现在具有20个元素的大小或长度。您可以使用size或length方法返回数组的大小 -
#!/ usr / bin / ruby names = Array 。新(20 ) 放名。size #返回20个 put名称。长度#这也返回20
输出结果如下 -
20 20
您可以按如下方式为数组中的每个元素分配一个值 -
#!/usr/bin/ruby names = Array.new(4, "mac") puts "#{names}"
输出结果如下 -
["mac", "mac", "mac", "mac"]
您还可以使用一个新的块,填充每个元素与块评估的 -
#!/usr/bin/ruby nums = Array.new(10) { |e| e = e * 2 } puts "#{nums}"
输出结果如下 -
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
还有另一种方法是Array,[]。它像这样工作 -
nums = Array.[](1, 2, 3, 4,5)
数组创建的另一种形式如下:
nums = Array[1, 2, 3, 4,5]
的内核在核心红宝石可用模块有一个数组的方法,其中仅接受一个参数。在这里,该方法将一个范围作为参数来创建一个数组数组 -
#!/usr/bin/ruby digits = Array(0..9) puts "#{digits}"
输出结果如下 -
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
我们需要一个Array对象的实例来调用Array方法。我们已经看到,以下是创建Array对象实例的方法 -
Array.[](...) [or] Array[...] [or] [...]
这将返回一个填充有给定对象的新数组。现在,使用创建的对象,我们可以调用任何可用的实例方法。例如 -
#!/usr/bin/ruby digits = Array(0..9) num = digits.at(6) puts "#{num}"
输出结果如下 -
6
尝试以下示例来打包各种数据。
a = [ "a", "b", "c" ] n = [ 65, 66, 67 ] puts a.pack("A3A3A3") #=> "a b c " puts a.pack("a3a3a3") #=> "a 00 00b 00 00c 00 00" puts n.pack("ccc") #=> "ABC"
输出结果如下 -
a b c abc ABC
哈希是这样的键值对的集合:“employee”=>“salary”。它类似于Array,除了通过任何对象类型的任意键完成索引,而不是整数索引。
通过键或值遍历哈希的顺序可能看起来是任意的,通常不会在插入顺序中。如果您尝试使用不存在的密钥访问哈希,该方法将返回nil。
与数组一样,有多种方法可以创建散列。您可以使用新的类方法创建一个空的散列-
months = Hash.new
您也可以使用new来创建具有默认值的哈希值,否则为零,
months = Hash.new( "month" ) or months = Hash.new "month"
当您访问具有默认值的哈希中的任何密钥时,如果该键或值不存在,则访问该哈希将返回默认值 -
#!/usr/bin/ruby months = Hash.new( "month" ) puts "#{months[0]}" puts "#{months[72]}"
输出结果如下 -
month
month
#!/usr/bin/ruby H = Hash["a" => 100, "b" => 200] puts "#{H["a"]}" puts "#{H["b"]}"
输出结果如下 -
100 200
您可以使用任何Ruby对象作为键或值,即使是数组,因此以下示例是有效的一个 -
[1,"jan"] => "January"
我们需要一个Hash对象的实例来调用Hash方法。正如我们所看到的,以下是创建Hash对象实例的方法 -
Hash[[key =>|, value]* ] or Hash.new [or] Hash.new(obj) [or] Hash.new { |hash, key| block }
这将返回一个填充有给定对象的新哈希值。现在使用创建的对象,我们可以调用任何可用的实例方法。例如 -
#!/usr/bin/ruby $, = ", " months = Hash.new( "month" ) months = {"1" => "January", "2" => "February"} keys = months.keys puts "#{keys}"
输出结果如下 -
["1", "2"]
以下是公共散列方法(假设hash是数组对象)
没有 | 方法与说明 |
---|---|
1 | 哈希== other_hash
基于它们是否具有相同数量的键值对,以及键值对是否匹配每个散列中的对应对,来测试两个散列是否相等。 |
2 | 散列键]
使用键引用哈希值。如果没有找到该键,则返回默认值。 |
3 | hash。[key] = value
将由值给出的值与由键给出的键相关联。 |
4 | hash.clear
从哈希中删除所有键值对。 |
5 | hash.default(key = nil)
返回hash的默认值,如果未设置,则返回nil =。(如果密钥在哈希中不存在,则返回默认值。) |
6 | hash.default = obj
设置hash的默认值。 |
7 | hash.default_proc
如果哈希是由块创建的,则返回一个块。 |
8 | hash.delete(key)[或] array.delete(key){| key | 块} 通过键从哈希中删除键值对。如果使用块,则如果未找到对,则返回块的结果。比较delete_if。 |
9 | hash.delete_if {| key,value | 块}
从哈希中删除键值对,每个块的值计算结果为true。 |
10 | hash.each {| key,value | 块}
迭代哈希,为每个键调用一次块,将键值传递为双元素数组。 |
11 | hash.each_key {| key | 块}
迭代哈希,为每个键调用一次块,将密钥作为参数传递。 |
12 | hash.each_key {| key_value_array | 块}
迭代哈希,为每个键调用一次块,将键和值作为参数传递。 |
13 | hash.each_key {| value | 块}
迭代哈希,为每个键调用一次块,将值作为参数传递。 |
14 | hash.empty?
测试哈希是否为空(不包含键值对),返回true或false。 |
15 | hash.fetch(key [,default])[或] hash.fetch(key){| 关键| 块} 返回给定键的哈希值。如果无法找到该键,并且没有其他参数,则会引发IndexError异常; 如果给出默认值,则返回; 如果指定了可选块,则返回其结果。 |
16 | hash.has_key?(key)[或] hash.include?(key)[or] hash.key?(key)[或] hash.member?(key) 测试哈希中是否存在给定的键,返回true或false。 |
17 | hash.has_value?(value)
测试哈希是否包含给定的值。 |
18 | hash.index(value)
返回键为给定值的哈希值,零,如果没有匹配值被发现。 |
19 | hash.indexes(键)
返回由给定键的值组成的新数组。将插入未找到的键的默认值。此方法已弃用。使用选择。 |
20 | hash.indices(键)
返回由给定键的值组成的新数组。将插入未找到的键的默认值。此方法已弃用。使用选择。 |
21 | hash.inspect
返回一个漂亮的打印字符string版本的哈希。 |
22 | hash.invert
创建一个新的哈希,从哈希转换键和值 ; 也就是说,在新的哈希中,来自哈希的键变为值和值成为键。 |
23 | hash.keys
使用哈希值创建一个新数组。 |
24 | hash.length
以整数形式返回哈希的大小或长度。 |
25 | hash.merge(other_hash)[或] hash.merge(other_hash){| key,oldval,newval | 块} 返回包含内容的新的哈希散列和other_hash,哈希与那些重复键覆盖对other_hash。 |
26 | hash.merge!(other_hash)[或] hash.merge!(other_hash){| key,oldval,newval | 块} 与合并相同,但更改已完成。 |
27 | hash.rehash
根据每个键的当前值重建散列。如果值插入后,值已更改,则此方法重新索引哈希。 |
28 | hash.reject {| key,value | 块}
为每个块创建一个新的哈希值,该块的计算结果为true |
29 | hash.reject!{| key,value | 块}
与拒绝相同,但是改变了。 |
30 | hash.replace(other_hash)
用other_hash的内容替换哈希的内容。 |
31 | hash.select {| key,value | 块}
返回选自键-值对的新数组散列的量,块返回真。 |
32 | hash.shift
从哈希中删除键值对,将其作为双元素数组返回。 |
33 | hash.size
以整数形式返回哈希的大小或长度。 |
34 | hash.sort
将哈希转换为包含键值对数组的二维数组,然后将其排序为数组。 |
35 | hash.store(key,value)
在哈希中存储键值对。 |
36 | hash.to_a
从哈希创建一个二维数组。每个键/值对被转换为一个数组,所有这些数组都存储在一个包含的数组中。 |
37 | hash.to_hash
返回hash(self)。 |
38 | hash.to_s
将哈希转换为数组,然后将该数组转换为字符string。 |
39 | hash.update(other_hash)[或] hash.update(other_hash){| key,oldval,newval | 块} 返回包含内容的新的哈希散列和other_hash,在覆盖对哈希与那些重复键other_hash。 |
40 | hash.value?(value)
测试哈希是否包含给定的值。 |
41 | 哈希值
返回一个包含所有hash值的新数组。 |
42 | hash.values_at(obj,...)
返回一个包含与给定键或键相关联的哈希值的新数组。 |
时间类表示日期和时间在Ruby中。它是操作系统提供的系统日期和时间功能的薄层。该课程可能无法在您的系统上表示1970年以前或2038年之后的日期。
本章让您熟悉日期和时间的所有最想要的概念。
以下是获取当前日期和时间的简单示例:
#!/usr/bin/ruby -w time1 = Time.new puts "Current Time : " + time1.inspect # Time.now is a synonym: time2 = Time.now puts "Current Time : " + time2.inspect
输出结果如下 -
Current Time : Mon Jun 02 12:02:39 -0700 2008 Current Time : Mon Jun 02 12:02:39 -0700 2008
我们可以使用Time对象来获取日期和时间的各种组件。以下是显示相同的例子 -
#!/usr/bin/ruby -w time = Time.new # Components of a Time puts "Current Time : " + time.inspect puts time.year # => Year of the date puts time.month # => Month of the date (1 to 12) puts time.day # => Day of the date (1 to 31 ) puts time.wday # => 0: Day of week: 0 is Sunday puts time.yday # => 365: Day of year puts time.hour # => 23: 24-hour clock puts time.min # => 59 puts time.sec # => 59 puts time.usec # => 999999: microseconds puts time.zone # => "UTC": timezone name
输出结果如下 -
Current Time : Mon Jun 02 12:03:08 -0700 2008 2008 6 2 1 154 12 3 8 247476 UTC
这两个函数可用于按照以下标准格式格式化日期:
# July 8, 2008 Time.local(2008, 7, 8) # July 8, 2008, 09:10am, local time Time.local(2008, 7, 8, 9, 10) # July 8, 2008, 09:10 UTC Time.utc(2008, 7, 8, 9, 10) # July 8, 2008, 09:10:11 GMT (same as UTC) Time.gm(2008, 7, 8, 9, 10, 11)
以下是以下列格式获取数组中的所有组件的示例:
[sec,min,hour,day,month,year,wday,yday,isdst,zone]
尝试以下 -
#!/usr/bin/ruby -w time = Time.new values = time.to_a p values
输出结果如下 -
[26, 10, 12, 2, 6, 2008, 1, 154, false, "MST"]
该数组可以传递给Time.utc或Time.local函数,以获取不同格式的日期如下:
#!/usr/bin/ruby -w time = Time.new values = time.to_a puts Time.utc(*values)
输出结果如下 -
Mon Jun 02 12:15:36 UTC 2008
以下是从(依赖于平台的)时代以内部时间表示时间的方式 -
# Returns number of seconds since epoch time = Time.now.to_i # Convert number of seconds into Time object. Time.at(time) # Returns second since epoch which includes microseconds time = Time.now.to_f
您可以使用Time对象获取有关Timezone的所有信息和夏令时如下:
time = Time.new # Here is the interpretation time.zone # => "UTC": return the timezone time.utc_offset # => 0: UTC is 0 seconds offset from UTC time.zone # => "PST" (or whatever your timezone is) time.isdst # => false: If UTC does not have DST. time.utc? # => true: if t is in UTC time zone time.localtime # Convert to local timezone. time.gmtime # Convert back to UTC. time.getlocal # Return a new Time object in local zone time.getutc # Return a new Time object in UTC
有多种方式来格式化日期和时间。这是一个例子,显示几个 -
#!/usr/bin/ruby -w time = Time.new puts time.to_s puts time.ctime puts time.localtime puts time.strftime("%Y-%m-%d %H:%M:%S")
输出结果如下 -
Mon Jun 02 12:35:19 -0700 2008 Mon Jun 2 12:35:19 2008 Mon Jun 02 12:35:19 -0700 2008 2008-06-02 12:35:19
下表中的这些指令与Time.strftime方法一起使用。
没有 | 指令和说明 |
---|---|
1 | %一个
缩写的工作日名称(Sun)。 |
2 | %一个
完整的工作日名称(星期日)。 |
3 | %b
缩写月份名称(Jan)。 |
4 | %B
全月份(1月)。 |
5 | %C
优选的本地日期和时间表示。 |
6 | %d
当天(01至31)。 |
7 | %H
24小时营业时间(00至23点)。 |
8 | %一世
一小时,12小时钟(01至12)。 |
9 | %j
今年(001至366)。 |
10 | %m
一月(01至12)。 |
11 | %M
一小时(00至59)。 |
12 | %p
经络指标(AM或PM)。 |
13 | %S
二分钟(00至60分)。 |
14 | %U
本周的周数,从第一个星期天开始,作为第一周的第一天(00到53)。 |
15 | %W
本周的周数,从第一个星期一开始,作为第一周的第一天(00到53)。 |
16 | %w
星期几(星期日为0,0至6)。 |
17 | %X
唯一的日期优先代表,没有时间。 |
18 | %X
唯一的优先代表,没有日期。 |
19 | %y
一年没有一个世纪(00到99)。 |
20 | %Y
年与世纪。 |
21 | %Z
时区名称。 |
22 | %%
字面%字符。 |
您可以按照以下时间执行简单的运算:
now = Time.now # Current time puts now past = now - 10 # 10 seconds ago. Time - number => Time puts past future = now + 10 # 10 seconds from now Time + number => Time puts future diff = future - now # => 10 Time - Time => number of seconds puts diff
输出结果如下 -
Thu Aug 01 20:57:05 -0700 2013 Thu Aug 01 20:56:55 -0700 2013 Thu Aug 01 20:57:15 -0700 2013 10.0
范围遍布各地:1月至12月,0至9,50至67行,依此类推。Ruby支持范围,并允许我们以各种方式使用范围 -
第一个也许最自然的使用范围是表达一个序列。序列具有起始点,终点和在序列中产生连续值的方法。
Ruby使用""..""和""...“范围运算符创建这些序列。双点格式创建一个包含范围,而三点形式创建一个排除指定高值的范围。
(1..5) #==> 1, 2, 3, 4, 5 (1...5) #==> 1, 2, 3, 4 ("a".."d") #==> "a", "b", "c", "d"
序列1..100被保持作为一个范围对象包含到两个引用Fixnum对象的对象。如果需要,您可以使用to_a方法将范围转换为列表。尝试以下示例 -
#!/usr/bin/ruby $, =", " # Array value separator range1 = (1..10).to_a range2 = ("bar".."bat").to_a puts "#{range1}" puts "#{range2}"
输出结果如下 -
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] ["bar", "bas", "bat"]
范围实现方法,让您迭代它们并以各种方式测试其内容 -
#!/usr/bin/ruby # Assume a range digits = 0..9 puts digits.include?(5) ret = digits.min puts "Min value is #{ret}" ret = digits.max puts "Max value is #{ret}" ret = digits.reject {|i| i < 5 } puts "Rejected values are #{ret}" digits.each do |digit| puts "In Loop #{digit}" end
输出结果如下 -
true Min value is 0 Max value is 9 Rejected values are 5, 6, 7, 8, 9 In Loop 0 In Loop 1 In Loop 2 In Loop 3 In Loop 4 In Loop 5 In Loop 6 In Loop 7 In Loop 8 In Loop 9
范围也可以用作条件表达式。例如,下面的代码片断打印设置从标准输入,其中,在每一组的第一行包含字线的开始和最后一行字结束 -
while gets print if /start/../end/ end
范例可用于案例陈述 -
#!/usr/bin/ruby score = 70 result = case score when 0..40 then "Fail" when 41..60 then "Pass" when 61..70 then "Pass with Merit" when 71..100 then "Pass with Distinction" else "Invalid Score" end puts result
输出结果如下 -
Pass with Merit
多功能范围的最终用途是作为间隔测试:查看某些值是否落在由范围表示的间隔内。这是使用===,case等式运算符完成的。
#!/usr/bin/ruby if ((1..10) === 5) puts "5 lies in (1..10)" end if (("a".."j") === "c") puts "c lies in ("a".."j")" end if (("a".."j") === "z") puts "z lies in ("a".."j")" end
输出结果如下 -
5 lies in (1..10) c lies in ("a".."j")
迭代器只不过是集合支持的方法。存储一组数据成员的对象称为集合。在Ruby中,数组和散列可以被称为集合。
迭代器一个接一个地返回一个集合的所有元素。我们将在这里探讨两个迭代器,每一个和收集。我们来看看这些细节。
每个迭代器返回数组或散列的所有元素。
collection.each do |variable| code end
对集合中的每个元素执行代码。这里,collection可能是一个数组或一个ruby哈希。
#!/usr/bin/ruby ary = [1,2,3,4,5] ary.each do |i| puts i end
输出结果如下 -
1 2 3 4 5
您总是将每个迭代器与一个块相关联。它将数组的每个值逐个返回到块。该值存储在变量i中,然后显示在屏幕上。
在收集迭代器返回一个集合中的所有元素。
collection = collection.collect
该收集方法不一定总是与块关联。的收集方法返回整个集合,无论它是否是一个数组或散列。
#!/usr/bin/ruby a = [1,2,3,4,5] b = Array.new b = a.collect puts b
输出结果如下 -
1 2 3 4 5
注意 - collect方法不是在数组之间进行复制的正确方法。还有一种称为克隆的方法,它应该用于将一个数组复制到另一个数组中。
当您想要使用每个值进行某些操作以获取新数组时,通常使用collect方法。例如,该代码产生的数组b含有10倍的每个值一个。
#!/usr/bin/ruby a = [1,2,3,4,5] b = a.collect{|x| 10*x} puts b
输出结果如下 -
10 20 30 40 50
Ruby提供了一组在内核模块中实现的I / O相关方法。所有的I / O方法都是从IO类派生的。
类IO提供了所有基本的方法,比如read,write,gets,puts,readline,getc和printf。
本章将介绍Ruby中可用的所有基本I / O功能。有关更多功能,请参阅Ruby Class IO。
在前面的章节中,您已将值分配给变量,然后使用puts语句打印输出。
该放语句指示程序显示存储在变量的值。这将在其写入的每一行的末尾添加一条新行。
#!/usr/bin/ruby val1 = "This is variable one" val2 = "This is variable two" puts val1 puts val2
输出结果如下 -
This is variable one This is variable two
在得到语句可用于采取从标准屏幕的用户称为STDIN任何输入。
以下代码显示如何使用gets语句。该代码将提示用户输入一个值,该值将存储在一个变量val中,最后将被打印在STDOUT上。
#!/usr/bin/ruby puts "Enter a value :" val = gets puts val
输出结果如下 -
Enter a value : This is entered value This is entered value
不同于将整个字符string输出到屏幕上的puts语句,putc语句可以一次输出一个字符。
以下代码的输出只是字符H -
#!/usr/bin/ruby str = "Hello Ruby!" putc str
输出结果如下 -
H
该打印语句是类似于放声明。唯一的区别是,put语句在打印内容之后到下一行,而使用print语句,光标位于同一行上。
#!/usr/bin/ruby print "Hello World" print "Good Morning"
输出结果如下 -
Hello WorldGood Morning
直到现在,您一直在读写标准的输入和输出。现在,我们将看到如何使用实际的数据文件。
您可以使用File.new方法创建一个File对象,用于读取,写入或两者,根据模式字符string。最后,您可以使用File.close方法关闭该文件。
aFile = File.new("filename", "mode") # ... process the file aFile.close
您可以使用File.open方法创建一个新的文件对象并将该文件对象分配给一个文件。然而,File.open和File.new方法之间有一个区别。不同之处在于File.open方法可以与一个块相关联,而您不能使用File.new方法执行相同操作。
File.open("filename", "mode") do |aFile| # ... process the file end
与“简单”I / O相同的方法可用于所有文件对象。所以,从标准输入中读取一行,并且aFile.gets从文件对象aFile读取一行。
然而,I / O对象提供了更多的访问方法,使我们的生活更轻松。
您可以使用sysread方法来读取文件的内容。当使用sysread方法时,您可以以任何模式打开文件。例如 -
以下是输入文本文件 -
This is a simple text file for testing purpose.
现在我们来试试看这个文件 -
#!/usr/bin/ruby aFile = File.new("input.txt", "r") if aFile content = aFile.sysread(20) puts content else puts "Unable to open file!" end
此语句将输出文件的前20个字符。文件指针现在将被放置在文件中的第21个字符。
您可以使用syswrite方法将内容写入文件。在使用syswrite方法时,需要以写入方式打开文件。例如 -
#!/usr/bin/ruby aFile = File.new("input.txt", "r+") if aFile aFile.syswrite("ABCDEF") else puts "Unable to open file!" end
此语句将在文件中写入“ABCDEF”。
此方法属于类File。方法every_byte始终与块相关联。考虑下面的代码示例 -
#!/usr/bin/ruby aFile = File.new("input.txt", "r+") if aFile aFile.syswrite("ABCDEF") aFile.each_byte {|ch| putc ch; putc ?. } else puts "Unable to open file!" end
字符逐个传递给变量ch,然后如下显示在屏幕上 -
s. .a. .s.i.m.p.l.e. .t.e.x.t. .f.i.l.e. .f.o.r. .t.e.s.t.i.n.g. .p.u.r.p.o.s.e... . .
类File是类IO的子类。类IO也有一些可以用来操作文件的方法。
其中一种IO类方法是IO.readlines。此方法逐行返回文件的内容。以下代码显示了使用IO.readlines的方法-
#!/usr/bin/ruby arr = IO.readlines("input.txt") puts arr[0] puts arr[1]
在这段代码中,变量arr是一个数组。文件input.txt的每一行将是数组arr中的一个元素。因此,arr [0]将包含第一行,而arr [1]将包含该文件的第二行。
此方法也逐行返回输出。方法foreach和方法readlines之间的区别在于方法foreach与块相关联。但是,与方法readlines不同,foreach不会返回数组。例如 -
#!/usr/bin/ruby IO.foreach("input.txt"){|block| puts block}
该代码将文件测试的内容逐行传递给可变块,然后输出将显示在屏幕上。
您可以使用重命名和删除方法以Ruby编程方式重命名和删除文件。
以下是重命名现有文件test1.txt的示例 -
#!/usr/bin/ruby # Rename a file from test1.txt to test2.txt File.rename( "test1.txt", "test2.txt" )
以下是删除现有文件test2.txt的示例 -
#!/usr/bin/ruby # Delete file test2.txt File.delete("test2.txt")
使用具有掩码的chmod方法来更改文件的模式或权限/访问列表 -
以下是将现有文件test.txt的模式更改为掩码值的示例-
#!/usr/bin/ruby file = File.new( "test.txt", "w" ) file.chmod( 0755 )
以下命令测试在打开文件之前是否存在文件 -
#!/usr/bin/ruby File.open("file.rb") if File::exists?( "file.rb" )
以下命令查询文件是否真的是一个文件 -
#!/usr/bin/ruby # This returns either true or false File.file?( "text.txt" )
以下命令查找给定的文件名是否为目录 -
#!/usr/bin/ruby # a directory File::directory?( "/usr/local/bin" ) # => true # a file File::directory?( "file.rb" ) # => false
以下命令查找文件是否可读,可写或可执行 -
#!/usr/bin/ruby File.readable?( "test.txt" ) # => true File.writable?( "test.txt" ) # => true File.executable?( "test.txt" ) # => false
以下命令查找该文件是否为零大小 -
#!/usr/bin/ruby File.zero?( "test.txt" ) # => true
以下命令返回文件的大小 -
#!/usr/bin/ruby File.size?( "text.txt" ) # => 1002
以下命令可用于找出一种文件类型 -
#!/usr/bin/ruby File::ftype( "test.txt" ) # => file
ftype方法通过返回以下文件,文件,目录,characterSpecial,blockSpecial,fifo,link,socket或unknown来识别文件的类型。
以下命令可用于查找文件何时创建,修改或上次访问 -
#!/usr/bin/ruby File::ctime( "test.txt" ) # => Fri May 09 10:06:37 -0700 2008 File::mtime( "text.txt" ) # => Fri May 09 10:44:44 -0700 2008 File::atime( "text.txt" ) # => Fri May 09 10:45:01 -0700 2008
所有文件都包含在各种目录中,而Ruby也没有处理这些问题。而File类处理文件,目录使用Dir类来处理。
要更改Ruby程序中的目录,请使用Dir.chdir,如下所示。此示例将当前目录更改为/ usr / bin。
Dir.chdir("/usr/bin")
你可以找到目前的目录与Dir.pwd -
puts Dir.pwd # This will return something like /usr/bin
您可以使用Dir.entries获取特定目录中的文件和目录列表-
puts Dir.entries("/usr/bin").join(" ")
Dir.entries返回一个包含指定目录中所有条目的数组。Dir.foreach提供了相同的功能 -
Dir.foreach("/usr/bin") do |entry| puts entry end
更简洁的获取目录列表的方法是使用Dir的类数组方法 -
Dir["/usr/bin/*"]
该Dir.mkdir可以用来创建目录-
Dir.mkdir("mynewdir")
您还可以使用mkdir为新目录(不是已存在的目录)设置权限 -
注意 - 掩码755将权限所有者,组,世界[任何人]设置为rwxr-xr-x,其中r = read,w = write和x = execute。
Dir.mkdir( "mynewdir", 755 )
该Dir.delete可以用来删除目录。的Dir.unlink和Dir.rmdir执行完全相同的功能,并提供了方便。
Dir.delete("testdir")
临时文件是在程序执行期间可能会短暂创建的文件,但不是永久性的信息存储。
Dir.tmpdir提供了当前系统上临时目录的路径,尽管默认情况下该方法不可用。为了使Dir.tmpdir可用,有必要使用require"tmpdir"。
您可以使用Dir.tmpdir与File.join来创建一个独立于平台的临时文件 -
require "tmpdir" tempfilename = File.join(Dir.tmpdir, "tingtong") tempfile = File.new(tempfilename, "w") tempfile.puts "This is a temporary file" tempfile.close File.delete(tempfilename)
此代码创建一个临时文件,向其中写入数据并将其删除。Ruby的标准库中还包括一个名为库将它视为可以为您创建临时文件-
require "tempfile" f = Tempfile.new("tingtong") f.puts "Hello" puts f.path f.close
这里是用于处理文件和目录的ruby内置函数 -
执行和异常总是在一起。如果您打开的文件不存在,那么如果您没有正确处理这种情况,那么您的程序被认为是质量差的。
如果发生异常,程序将停止。因此,异常用于处理可能在程序执行期间发生的各种类型的错误,并采取适当的措施,而不是完全停止程序。
Ruby提供了一个很好的机制来处理异常。我们包含可能在开始/结束块中引发异常的代码,并使用rescue子句来告诉Ruby我们要处理的异常类型。
begin # - rescue OneTypeOfException # - rescue AnotherTypeOfException # - else # Other exceptions ensure # Always will be executed end
从开始到救援的一切都受到保护。如果在执行该代码块期间发生异常,则控制将传递到在rescue和end之间的块。
对于begin块中的每个rescue子句,Ruby会依次对比引用的异常与每个参数。如果rescue子句中命名的异常与当前抛出的异常的类型相同,或者是异常的超类,则匹配将成功。
在异常与指定的任何错误类型不匹配的情况下,我们允许在所有rescue子句之后使用else子句。
#!/usr/bin/ruby begin file = open("/unexistant_file") if file puts "File opened successfully" end rescue file = STDIN end print file, "==", STDIN, " "
输出结果如下。您可以看到STDIN被替换为文件,因为打开失败。
#<IO:0xb7d16f84>==#<IO:0xb7d16f84>
您可以使用rescue块捕获异常,然后使用retry语句从头开始执行begin块。
begin # Exceptions raised by this code will # be caught by the following rescue clause rescue # This block will capture all types of exceptions retry # This will move control to the beginning of begin end
#!/usr/bin/ruby begin file = open("/unexistant_file") if file puts "File opened successfully" end rescue fname = "existant_file" retry end
以下是流程的流程 -
注 - 请注意,如果重新替换的名称的文件不存在,则此示例代码将无限次重试。如果您使用重试进行异常处理,请小心。
您可以使用raise语句来引发异常。以下方法会在调用时引发异常。这是第二条消息将被打印出来。
raise OR raise "Error Message" OR raise ExceptionType, "Error Message" OR raise ExceptionType, "Error Message" condition
第一种形式只是重新引发当前的异常(如果没有当前的异常,则是RuntimeError)。这在异常处理程序中使用,需要在传递异常处理程序之前拦截异常。
第二种形式创建一个新的RuntimeError异常,将其消息设置为给定的字符string。然后,这个异常被提升为调用堆栈。
第三个表单使用第一个参数创建一个异常,然后将关联的消息设置为第二个参数。
第四种形式与第三种形式相似,但您可以添加任何条件语句,除非引发异常。
#!/usr/bin/ruby begin puts "I am before the raise." raise "An error has occurred." puts "I am after the raise." rescue puts "I am rescued." end puts "I am after the begin block."
输出结果如下 -
I am before the raise. I am rescued. I am after the begin block.
另外一个例子显示了加注的用法-
#!/usr/bin/ruby begin raise "A test exception." rescue Exception => e puts e.message puts e.backtrace.inspect end
输出结果如下 -
A test exception. ["main.rb:4"]
有时候,您需要保证在代码块结束时进行一些处理,无论是否引发异常。例如,您可能有一个文件打开,进入该块,并且您需要确保它在块退出时关闭。
在保证条款不只是这个。确保在最后一个救援条款之后,并包含一段代码,该块代码将随着块终止而始终执行。如果块正常退出,如果它引发和拯救异常,或者如果被未捕获的异常终止,则确保块将被运行,这并不重要。
begin #.. process #..raise exception rescue #.. handle error ensure #.. finally ensure execution #.. This will always execute. end
begin raise "A test exception." rescue Exception => e puts e.message puts e.backtrace.inspect ensure puts "Ensuring execution" end
输出结果如下 -
A test exception. ["main.rb:4"] Ensuring execution
如果else子句存在,则遵循救援条款和任何确认。
一个身体否则只有在没有异常是由代码的主体提出的条款执行。
begin #.. process #..raise exception rescue # .. handle error else #.. executes if there is no exception ensure #.. finally ensure execution #.. This will always execute. end
begin # raise "A test exception." puts "I"m not raising exception" rescue Exception => e puts e.message puts e.backtrace.inspect else puts "Congratulations-- no errors!" ensure puts "Ensuring execution" end
输出结果如下 -
I"m not raising exception Congratulations-- no errors! Ensuring execution
引发的错误信息可以使用$!变量。
虽然提升和救援的例外机制对于在出现问题时放弃执行是伟大的,但是在正常处理期间能够跳出一些深入嵌套的构造有时是很好的。这是抓住和抛出来派上用场的地方。
捕获限定了标记的具有给定名称(其可以是符号或字符string)的块。块正常执行,直到遇到一个投掷。
throw :lablename #.. this will not be executed catch :lablename do #.. matching catch will be executed after a throw is encountered. end OR throw :lablename condition #.. this will not be executed catch :lablename do #.. matching catch will be executed after a throw is encountered. end
以下示例使用throw来终止与用户的交互,如果“!” 是响应任何提示输入。
def promptAndGet(prompt) print prompt res = readline.chomp throw :quitRequested if res == "!" return res end catch :quitRequested do name = promptAndGet("Name: ") age = promptAndGet("Age: ") sex = promptAndGet("Sex: ") # .. # process information end promptAndGet("Name:")
您应该在机器上尝试上述程序,因为它需要手动交互。输出结果如下 -
Name: Ruby on Rails Age: 3 Sex: ! Name:Just Ruby
Ruby的标准类和模块引发异常。所有的异常类都形成一个层次结构,其顶层有Exception类。下一级包含七种不同的类型 -
在这个级别还有一个例外,Fatal,但Ruby解释器只在内部使用。
ScriptError和StandardError都有多个子类,但是我们不需要在这里详细介绍。重要的是,如果我们创建我们自己的异常类,它们需要是类Exception或其后代之一的子类。
我们来看一个例子 -
class FileSaveError < StandardError attr_reader :reason def initialize(reason) @reason = reason end end
现在,看下面的例子,这将使用这个异常 -
File.open(path, "w") do |file| begin # Write out the data ... rescue # Something went wrong! raise FileSaveError.new($!) end end
这里重要的一点是提高FileSaveError.new($!)。我们调用raise来表示发生了异常,传递一个新的FileSaveError实例,原因是特定的异常导致数据写入失败。
Ruby是一种纯粹的面向对象的语言,Ruby都是一个对象。Ruby中的每个值都是一个对象,即使是最原始的东西:字符string,数字甚至是真假。即使是一个类本身是一个对象是所述的实例类类。本章将介绍与面向对象Ruby相关的所有主要功能。
一个类用于指定一个对象的形式,它将数据表示和方法结合起来,将数据操作成一个整齐的包。类中的数据和方法称为类的成员。
定义类时,可以为数据类型定义蓝图。这实际上并不定义任何数据,但它确实定义了类名称是什么意思,也就是说,类的对象将由哪个对象组成,哪些操作可以在这样的对象上执行。
类定义从关键字类开始,后跟类名称,并以结尾分隔。例如,我们使用关键字类定义了Box类,如下所示:
class Box code end
名称必须以大写字母开头,并且包含多个单词的约定名称与每个大写字母一起运行,没有分隔符(CamelCase)。
一个类提供了对象的蓝图,所以基本上从一个类创建一个对象。我们使用new关键字声明类的对象。以下语句声明类Box的两个对象 -
box1 = Box.new box2 = Box.new
initialize方法是一个标准的Ruby类方法和工作方式几乎相同的方式,构造函数在其他面向对象编程语言的作品。当您要在创建对象时初始化一些类变量时,initialize方法很有用。这个方法可能需要一个参数列表,像其他的ruby方法一样,它将在之前的def关键字如下所示:
class Box def initialize(w,h) @width, @height = w, h end end
实例变量是一种类属性的,他们就成为对象的属性一旦被使用类创建的对象。每个对象的属性都被单独分配,与其他对象不共享任何值。它们使用类中的@运算符进行访问,但是在使用公共方法的类之外访问它们,这些方法称为访问器方法。如果我们采用上面定义的类Box,那么@width和@height是类Box的实例变量。
class Box def initialize(w,h) # assign instance variables @width, @height = w, h end end
为了使变量从类外部可用,它们必须在访问器方法中定义,这些访问器方法也称为getter方法。以下示例显示了访问器方法的用法 -
#!/usr/bin/ruby -w # define a class class Box # constructor method def initialize(w,h) @width, @height = w, h end # accessor methods def printWidth @width end def printHeight @height end end # create an object box = Box.new(10, 20) # use accessor methods x = box.printWidth() y = box.printHeight() puts "Width of the box is : #{x}" puts "Height of the box is : #{y}"
当执行上述代码时,输出结果如下-
Width of the box is : 10 Height of the box is : 20
类似于访问方法,用于访问变量的值,Ruby提供了一种使用setter方法从类外部设置这些变量的值的方法,定义如下:
#!/usr/bin/ruby -w # define a class class Box # constructor method def initialize(w,h) @width, @height = w, h end # accessor methods def getWidth @width end def getHeight @height end # setter methods def setWidth=(value) @width = value end def setHeight=(value) @height = value end end # create an object box = Box.new(10, 20) # use setter methods box.setWidth = 30 box.setHeight = 50 # use accessor methods x = box.getWidth() y = box.getHeight() puts "Width of the box is : #{x}" puts "Height of the box is : #{y}"
当执行上述代码时,输出结果如下-
Width of the box is : 30 Height of the box is : 50
在实例方法中以相同的方式也被定义为我们定义使用任何其它方法DEF关键字和它们只能使用一个类的实例如下所示来使用。它们的功能不限于访问实例变量,而且还可以根据您的要求进行更多操作。
#!/usr/bin/ruby -w # define a class class Box # constructor method def initialize(w,h) @width, @height = w, h end # instance method def getArea @width * @height end end # create an object box = Box.new(10, 20) # call instance methods a = box.getArea() puts "Area of the box is : #{a}"
当执行上述代码时,输出结果如下-
Area of the box is : 200
的类变量是一个变量,它是一个类的所有实例之间共享。换句话说,有一个变量的实例,它被对象实例访问。类变量前面加上两个@字符(@@)。类变量必须在类定义内初始化,如下所示。
使用def self.methodname()定义类方法,该方法以末尾分隔符结尾,并使用类名称作为classname.methodname调用,如以下示例所示 -
#!/usr/bin/ruby -w class Box # Initialize our class variables @@count = 0 def initialize(w,h) # assign instance avriables @width, @height = w, h @@count += 1 end def self.printCount() puts "Box count is : #@@count" end end # create two object box1 = Box.new(10, 20) box2 = Box.new(30, 100) # call class method to print box count Box.printCount()
当执行上述代码时,输出结果如下-
Box count is : 2
您定义的任何类都应该有一个to_s实例方法来返回对象的字符string表示形式。以下是一个简单的例子来表示一个Box对象的宽度和高度 -
#!/usr/bin/ruby -w class Box # constructor method def initialize(w,h) @width, @height = w, h end # define to_s method def to_s "(w:#@width,h:#@height)" # string formatting of the object. end end # create an object box = Box.new(10, 20) # to_s method will be called in reference of string automatically. puts "String representation of box is : #{box}"
当执行上述代码时,输出结果如下-
String representation of box is : (w:10,h:20)
Ruby在实例方法级别提供三级保护,可能是公共的,私有的或受保护的。Ruby不对实例和类变量应用任何访问控制。
公共方法 - 任何人都可以调用公共方法。默认情况下,方法是公开的,除了初始化,它始终是私有的。
私有方法 - 无法访问私有方法,甚至无法从课外查看。只有类方法可以访问私有成员。
受保护的方法 - 受保护的方法只能由定义类的对象及其子类调用。访问权限在家庭内。
以下是一个简单的示例来显示所有三个访问修饰符的语法 -
#!/usr/bin/ruby -w # define a class class Box # constructor method def initialize(w,h) @width, @height = w, h end # instance method by default it is public def getArea getWidth() * getHeight end # define private accessor methods def getWidth @width end def getHeight @height end # make them private private :getWidth, :getHeight # instance method to print area def printArea @area = getWidth() * getHeight puts "Big box area is : #@area" end # make it protected protected :printArea end # create an object box = Box.new(10, 20) # call instance methods a = box.getArea() puts "Area of the box is : #{a}" # try to call protected or methods box.printArea()
当执行上述代码时,会产生以下结果。这里,第一种方法被称为成功,但第二种方法给了一个问题。
Area of the box is : 200 test.rb:42: protected method `printArea" called for # <Box:0xb7f11280 @height = 20, @width = 10> (NoMethodError)
面向对象编程中最重要的概念之一是继承。继承允许我们根据另一个类定义一个类,这样可以更容易地创建和维护应用程序。
继承还提供了重用代码功能和快速实施时间的机会,但不幸的是,Ruby不支持多级继承,而Ruby支持mixins。mixin就像多继承的专门实现,只有接口部分被继承。
当创建一个类时,程序员可以指定新类应该继承现有类的成员,而不是编写全新的数据成员和成员函数。这个现有的类称为基类或超类,新类称为派生类或子类。
Ruby还支持子类化的概念,即继承,下面的例子解释了这个概念。扩展类的语法很简单。只需添加一个<character和超类的名称到你的class语句。例如,下面将一个类BigBox定义为Box的子类-
#!/usr/bin/ruby -w # define a class class Box # constructor method def initialize(w,h) @width, @height = w, h end # instance method def getArea @width * @height end end # define a subclass class BigBox < Box # add a new instance method def printArea @area = @width * @height puts "Big box area is : #@area" end end # create an object box = BigBox.new(10, 20) # print the area box.printArea()
当执行上述代码时,输出结果如下-
Big box area is : 200
虽然您可以在派生类中添加新功能,但有时您希望更改父类中已定义方法的行为。您可以简单地通过保持方法名称相同,并覆盖方法的功能,如下例所示:
#!/usr/bin/ruby -w # define a class class Box # constructor method def initialize(w,h) @width, @height = w, h end # instance method def getArea @width * @height end end # define a subclass class BigBox < Box # change existing getArea method as follows def getArea @area = @width * @height puts "Big box area is : #@area" end end # create an object box = BigBox.new(10, 20) # print the area using overriden method. box.getArea()
我们希望+运算符使用+执行两个Box对象的向量加法,*运算符将Box的宽度和高度乘以一个标量,一元运算符来否定Box的宽度和高度。这里是一个具有数学运算符定义的Box类的版本 -
class Box def initialize(w,h) # Initialize the width and height @width,@height = w, h end def +(other) # Define + to do vector addition Box.new(@width + other.width, @height + other.height) end def -@ # Define unary minus to negate width and height Box.new(-@width, -@height) end def *(scalar) # To perform scalar multiplication Box.new(@width*scalar, @height*scalar) end end
有时,我们想防止对象被更改。Object中的冻结方法允许我们这样做,有效地将对象变成一个常量。任何对象都可以通过调用Object.freeze来冻结。冻结对象可能不被修改:您不能更改其实例变量。
您可以使用Object.frozen检查给定对象是否已被冻结?方法,如果对象被冻结,返回true,否则返回false值。以下示例清除概念 -
#!/usr/bin/ruby -w # define a class class Box # constructor method def initialize(w,h) @width, @height = w, h end # accessor methods def getWidth @width end def getHeight @height end # setter methods def setWidth=(value) @width = value end def setHeight=(value) @height = value end end # create an object box = Box.new(10, 20) # let us freez this object box.freeze if( box.frozen? ) puts "Box object is frozen object" else puts "Box object is normal object" end # now try using setter methods box.setWidth = 30 box.setHeight = 50 # use accessor methods x = box.getWidth() y = box.getHeight() puts "Width of the box is : #{x}" puts "Height of the box is : #{y}"
当执行上述代码时,输出结果如下-
Box object is frozen object test.rb:20:in `setWidth=": can"t modify frozen object (TypeError) from test.rb:39
您可以通过将直接数字或字符string值分配给变量来定义类中的常量,该变量定义为不使用@或@@。按照惯例,我们保持常数名字大写。
一旦定义了一个常量,你不能改变它的值,但你可以直接在一个类中直接访问一个变量,就像一个变量一样,但是如果你想访问类之外的一个常量,那么你必须使用classname :: constant,如下面的例子。
#!/usr/bin/ruby -w # define a class class Box BOX_COMPANY = "TATA Inc" BOXWEIGHT = 10 # constructor method def initialize(w,h) @width, @height = w, h end # instance method def getArea @width * @height end end # create an object box = Box.new(10, 20) # call instance methods a = box.getArea() puts "Area of the box is : #{a}" puts Box::BOX_COMPANY puts "Box weight is: #{Box::BOXWEIGHT}"
当执行上述代码时,输出结果如下-
Area of the box is : 200 TATA Inc Box weight is: 10
类常量是继承的,可以像实例方法一样被覆盖。
当您想要创建一个对象而不调用其构造函数初始化即使用新方法时,可能会出现这种情况,在这种情况下,您可以调用allocate,这将为您创建一个未初始化的对象,如下例所示:
#!/usr/bin/ruby -w # define a class class Box attr_accessor :width, :height # constructor method def initialize(w,h) @width, @height = w, h end # instance method def getArea @width * @height end end # create an object using new box1 = Box.new(10, 20) # create another object using allocate box2 = Box.allocate # call instance method using box1 a = box1.getArea() puts "Area of the box is : #{a}" # call instance method using box2 a = box2.getArea() puts "Area of the box is : #{a}"
当执行上述代码时,输出结果如下-
Area of the box is : 200 test.rb:14: warning: instance variable @width not initialized test.rb:14: warning: instance variable @height not initialized test.rb:14:in `getArea": undefined method `*" for nil:NilClass (NoMethodError) from test.rb:29
如果类定义是可执行代码,这意味着它们在某个对象的上下文中执行:self必须引用某些对象。我们来看看它是什么
#!/usr/bin/ruby -w class Box # print class information puts "Type of self = #{self.type}" puts "Name of self = #{self.name}" end
当执行上述代码时,输出结果如下-
Type of self = Class Name of self = Box
这意味着使用该类作为当前对象执行类定义。这意味着在执行方法定义时,元类及其超类中的方法将可用。
一个正则表达式是一个字符的特殊序列,可帮助您匹配或查找使用的模式举办了专门的语法其他字符string或字符string集。
甲正则表达式文本是斜线之间或任意分隔符接着%R如下之间的图案-
/pattern/ /pattern/im # option can be specified %r!/usr/local! # general delimited regular expression
#!/usr/bin/ruby line1 = "Cats are smarter than dogs"; line2 = "Dogs also like meat"; if ( line1 =~ /Cats(.*)/ ) puts "Line1 contains Cats" end if ( line2 =~ /Cats(.*)/ ) puts "Line2 contains Dogs" end
输出结果如下 -
Line1 contains Cats
正则表达式文字可能包含一个可选修饰符,用于控制匹配的各个方面。修饰符在第二个斜杠字符之后指定,如前所示,可以由以下字符之一表示 -
没有 | 修饰和说明 |
---|---|
1 | 一世
忽略匹配文本时的情况。 |
2 | o
执行#{}插值仅一次,第一次对正则表达式文字进行评估。 |
3 | X
忽略空格,并允许在正则表达式中的注释。 |
4 | m
匹配多行,将换行符识别为常规字符。 |
5 | u,e,s,n
将正则表达式解释为Unicode(UTF-8),EUC,SJIS或ASCII。如果没有指定这些修饰符,则假定正则表达式使用源编码。 |
像使用%Q分隔的字符string文字,Ruby允许您使用%r开始正则表达式,然后是您选择的分隔符。当您描述的模式包含许多您不想逃脱的正斜杠字符时,这很有用
# Following matches a single slash character, no escape required %r|/| # Flag characters are allowed with this syntax, too %r[</(.*)>]i
除了控制字符(+?。* ^ $()[] {} | ),所有字符都与其自身匹配。您可以通过使用反斜杠将其转换为控制字符。
一些使用正则表达式的最重要的String方法是sub和gsub,它们的就地变体sub!和gsub!。
所有这些方法使用Regexp模式执行搜索和替换操作。该子与子!替换第一次出现的模式和gsub&gsub!取代所有事件。
子和GSUB返回一个新字符string,离开原来的地方未修改作为子!和gsub!修改它们被调用的字符string。
以下是这个例子 -
#!/usr/bin/ruby phone = "2004-959-559 #This is Phone Number" # Delete Ruby-style comments phone = phone.sub!(/#.*$/, "") puts "Phone Num : #{phone}" # Remove anything other than digits phone = phone.gsub!(/D/, "") puts "Phone Num : #{phone}"
输出结果如下 -
Phone Num : 2004-959-559 Phone Num : 2004959559
以下是另一个例子 -
#!/usr/bin/ruby text = "rails are rails, really good Ruby on Rails" # Change "rails" to "Rails" throughout text.gsub!("rails", "Rails") # Capitalize the word "Rails" throughout text.gsub!(/rails/, "Rails") puts "#{text}"
输出结果如下 -
Rails are Rails, really good Ruby on Rails
本章教你如何使用Ruby访问数据库。的红宝石DBI模块提供类似于Perl DBI模块的Ruby脚本独立于数据库的接口。
DBI代表Ruby的数据库独立接口,这意味着DBI在Ruby代码和底层数据库之间提供了一个抽象层,使您可以轻松地切换数据库实现。它定义了一组方法,变量和约定,提供一致的数据库接口,与实际使用的数据库无关。
DBI可以与以下接口连接 -
DBI独立于后端中可用的任何数据库。您可以使用DBI,无论您是使用Oracle,MySQL还是Informix等。从以下体系结构图中可以清楚看出。
Ruby DBI的一般架构使用两层 -
数据库接口(DBI)层。该层是数据库独立的,并提供了一组常用的访问方法,使用相同的方式,而不管您正在与之通信的数据库服务器的类型。
数据库驱动程序(DBD)层。此层数据库依赖; 不同的驱动程序可以访问不同的数据库引擎。MySQL有一个驱动程序,另一个用于PostgreSQL,另一个用于InterBase,另一个用于Oracle,等等。每个驱动程序解释来自DBI层的请求,并将它们映射到适合给定类型的数据库服务器的请求。
如果要编写Ruby脚本来访问MySQL数据库,则需要安装Ruby MySQL模块。
该模块作为DBD,如上所述,可从https://www.tmtm.org/en/mysql/ruby/下载
您可以从以下位置下载并安装Ruby DBI模块 -
http://rubyforge.org/projects/ruby-dbi/
在开始此安装之前,请确保您具有root权限。现在,按照下面给出的步骤 -
$ tar zxf dbi-0.2.0.tar.gz
进入分发目录dbi-0.2.0 nd,然后使用该目录中的setup.rb脚本进行配置。最通用的配置命令如下,配置参数后面没有参数。默认情况下,此命令配置分发以安装所有驱动程序。
$ ruby setup.rb config
更具体地说,提供--with选项,列出您要使用的分发的特定部分。例如,仅配置主DBI模块和MySQL DBD级别驱动程序,请执行以下命令 -
$ ruby setup.rb config --with = dbi,dbd_mysql
最后一步是创建驱动程序并使用以下命令进行安装 -
$ ruby setup.rb setup $ ruby setup.rb install
假设我们要使用MySQL数据库,在连接到数据库之前,请确保以下内容 -
您已经创建了一个数据库TESTDB。
您已在TESTDB中创建了EMPLOYEE。
该表格包含FIRST_NAME,LAST_NAME,AGE,SEX和收入字段。
用户ID“testuser”和密码“test123”设置为访问TESTDB。
Ruby Module DBI已正确安装在您的机器上。
您已经通过MySQL教程了解MySQL基础知识。
以下是与MySQL数据库“TESTDB”连接的示例
#!/usr/bin/ruby -w require "dbi" begin # connect to the MySQL server dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123") # get server version string and display it row = dbh.select_one("SELECT VERSION()") puts "Server version: " + row[0] rescue DBI::DatabaseError => e puts "An error occurred" puts "Error code: #{e.err}" puts "Error message: #{e.errstr}" ensure # disconnect from server dbh.disconnect if dbh end
在运行此脚本时,它会在我们的Linux机器上产生以下结果。
Server version: 5.0.45
如果使用数据源建立连接,则会返回数据库句柄并将其保存到dbh中以供进一步使用,否则dbh设置为nil值,e.err和e :: errstr分别返回错误代码和错误字符string。
最后,在出来之前,确保数据库连接关闭,资源释放。
当您要将记录创建到数据库表中时,需要执行INSERT操作。
建立数据库连接后,我们可以使用do方法或prepare和execute方法将表或记录创建到数据库表中。
不返回行的语句可以通过调用do数据库句柄方法来发出。此方法接受一个语句string参数,并返回受该语句影响的行数的计数。
dbh.do("DROP TABLE IF EXISTS EMPLOYEE") dbh.do("CREATE TABLE EMPLOYEE ( FIRST_NAME CHAR(20) NOT NULL, LAST_NAME CHAR(20), AGE INT, SEX CHAR(1), INCOME FLOAT )" );
类似地,您可以执行SQL INSERT语句以在EMPLOYEE表中创建记录。
#!/usr/bin/ruby -w require "dbi" begin # connect to the MySQL server dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123") dbh.do( "INSERT INTO EMPLOYEE(FIRST_NAME, LAST_NAME, AGE, SEX, INCOME) VALUES ("Mac", "Mohan", 20, "M", 2000)" ) puts "Record has been created" dbh.commit rescue DBI::DatabaseError => e puts "An error occurred" puts "Error code: #{e.err}" puts "Error message: #{e.errstr}" dbh.rollback ensure # disconnect from server dbh.disconnect if dbh end
您可以使用DBI类的prepare和execute方法通过Ruby代码执行SQL语句。
记录创建需要以下步骤:
使用INSERT语句准备SQL语句。这将使用prepare方法完成。
执行SQL查询以从数据库中选择所有结果。这将使用execute方法完成。
发布声明句柄。这将使用完成 API 完成
如果一切顺利,则提交此操作,否则您可以回滚完整的事务。
以下是使用这两种方法的语法 -
sth = dbh.prepare(statement) sth.execute ... zero or more SQL operations ... sth.finish
这两种方法可用于将绑定值传递给SQL语句。可能会提前输入要输入的值的情况。在这种情况下,使用结合值。使用问号(?)代替实际值,然后通过execute()API传递实际值。
以下是在EMPLOYEE表中创建两个记录的示例 -
#!/usr/bin/ruby -w require "dbi" begin # connect to the MySQL server dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123") sth = dbh.prepare( "INSERT INTO EMPLOYEE(FIRST_NAME, LAST_NAME, AGE, SEX, INCOME) VALUES (?, ?, ?, ?, ?)" ) sth.execute("John", "Poul", 25, "M", 2300) sth.execute("Zara", "Ali", 17, "F", 1000) sth.finish dbh.commit puts "Record has been created" rescue DBI::DatabaseError => e puts "An error occurred" puts "Error code: #{e.err}" puts "Error message: #{e.errstr}" dbh.rollback ensure # disconnect from server dbh.disconnect if dbh end
如果一次有多个INSERT,那么首先准备一个语句,然后在循环中多次执行一个语句比每次循环调用更有效。
任何数据库上的READ操作意味着从数据库中获取一些有用的信息。
一旦建立了数据库连接,我们就可以对这个数据库进行查询了。我们可以使用do方法或准备和执行方法从数据库表中获取值。
记录提取需要以下步骤 -
根据需要准备SQL查询。这将使用prepare方法完成。
执行SQL查询以从数据库中选择所有结果。这将使用execute方法完成。
逐个获取所有结果并打印这些结果。这将使用fetch方法完成。
发布声明句柄。这将使用finish方法完成。
以下是从薪水超过1000的EMPLOYEE表中查询所有记录的过程。
#!/usr/bin/ruby -w require "dbi" begin # connect to the MySQL server dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123") sth = dbh.prepare("SELECT * FROM EMPLOYEE WHERE INCOME > ?") sth.execute(1000) sth.fetch do |row| printf "First Name: %s, Last Name : %s ", row[0], row[1] printf "Age: %d, Sex : %s ", row[2], row[3] printf "Salary :%d ", row[4] end sth.finish rescue DBI::DatabaseError => e puts "An error occurred" puts "Error code: #{e.err}" puts "Error message: #{e.errstr}" ensure # disconnect from server dbh.disconnect if dbh end
输出结果如下 -
First Name: Mac, Last Name : Mohan Age: 20, Sex : M Salary :2000 First Name: John, Last Name : Poul Age: 25, Sex : M Salary :2300
从数据库中获取记录的方法有更多。如果您有兴趣,请通过提取结果,否则请继续下一节。
UPDATE对任何数据库的操作意味着更新数据库中已有的一个或多个记录。以下是将SEX的所有记录更新为“M”的过程。在这里,我们将所有男性的年龄增加一年。这将需要三个步骤 -
根据需要准备SQL查询。这将使用prepare方法完成。
执行SQL查询以从数据库中选择所有结果。这将使用execute方法完成。
发布声明句柄。这将使用finish方法完成。
如果一切顺利,则提交此操作,否则您可以回滚完整的事务。
#!/usr/bin/ruby -w require "dbi" begin # connect to the MySQL server dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123") sth = dbh.prepare("UPDATE EMPLOYEE SET AGE = AGE + 1 WHERE SEX = ?") sth.execute("M") sth.finish dbh.commit rescue DBI::DatabaseError => e puts "An error occurred" puts "Error code: #{e.err}" puts "Error message: #{e.errstr}" dbh.rollback ensure # disconnect from server dbh.disconnect if dbh end
当您要从数据库中删除一些记录时,需要执行DELETE操作。以下是从EMPLOYEE中删除AGE超过20的所有记录的过程。此操作将执行以下步骤。
根据需要准备SQL查询。这将使用prepare方法完成。
执行SQL查询从数据库中删除所需的记录。这将使用execute方法完成。
发布声明句柄。这将使用finish方法完成。
如果一切顺利,则提交此操作,否则您可以回滚完整的事务。
#!/usr/bin/ruby -w require "dbi" begin # connect to the MySQL server dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123") sth = dbh.prepare("DELETE FROM EMPLOYEE WHERE AGE > ?") sth.execute(20) sth.finish dbh.commit rescue DBI::DatabaseError => e puts "An error occurred" puts "Error code: #{e.err}" puts "Error message: #{e.errstr}" dbh.rollback ensure # disconnect from server dbh.disconnect if dbh end
事务是确保数据一致性的一种机制。事物应具有以下四个属性 -
原子性 - 事物完成或完全没有发生。
一致性 - 事物必须以一致的状态开始,并离开系统是一致的状态。
隔离 - 事务的中间结果在当前事务外部不可见。
耐久性 - 一旦提交了一个事务,甚至在系统发生故障后,效果也是持续的。
DBI提供两种提交或回滚事务的方法。还有一种称为事务的方法可用于实现事务。实施事物有两种简单的方法 -
第一种方法使用DBI的提交和回滚方法显式提交或取消事务 -
dbh["AutoCommit"] = false # Set auto commit to false. begin dbh.do("UPDATE EMPLOYEE SET AGE = AGE+1 WHERE FIRST_NAME = "John"") dbh.do("UPDATE EMPLOYEE SET AGE = AGE+1 WHERE FIRST_NAME = "Zara"") dbh.commit rescue puts "transaction failed" dbh.rollback end dbh["AutoCommit"] = true
第二种方法使用事务方法。这更简单,因为它需要一个包含构成事务的语句的代码块。的事物方法执行块,然后调用提交或回滚自动,这取决于该块是否成功或失败-
dbh["AutoCommit"] = false # Set auto commit to false. dbh.transaction do |dbh| dbh.do("UPDATE EMPLOYEE SET AGE = AGE+1 WHERE FIRST_NAME = "John"") dbh.do("UPDATE EMPLOYEE SET AGE = AGE+1 WHERE FIRST_NAME = "Zara"") end dbh["AutoCommit"] = true
提交是操作,它给数据库提供一个绿色信号来完成更改,并且在此操作之后,没有更改可以恢复。
这是一个简单的例子来调用commit方法。
dbh.commit
如果您对一个或多个更改不满意,并且要完全还原这些更改,请使用回滚方法。
这是一个简单的例子来调用回滚方法。
dbh.rollback
要断开数据库连接,请使用disconnect API。
dbh.disconnect
如果与数据库的连接由用户断开连接方法关闭,任何未完成的事务将由DBI回滚。然而,而不是依赖于DBI的任何实现细节,您的应用程序将更好地明确地调用提交或回滚。
有很多错误来源。一些示例是执行的SQL语句中的语法错误,连接失败或为已取消或已完成的语句句柄调用fetch方法。
如果DBI方法失败,DBI会引发异常。DBI方法可能引发几种类型的异常,但是两个最重要的异常类是DBI :: InterfaceError和DBI :: DatabaseError。
这些类的异常对象有三个名为err,errstr和state的属性,它们表示错误号,描述性错误字符string和标准错误代码。属性如下所示 -
ERR -返回错误发生或的整数表示零,如果这不是由DBD.The甲骨文DBD例如支持返回的数字部分ORA-XXXX的错误消息。
errstr - 返回发生错误的字符string表示形式。
state - 返回发生错误的SQLSTATE代码。SQLSTATE是一个五个字符长的字符string。大多数DBD不支持这个,而是返回nil。
在大多数示例中,您已经看到以下代码:
rescue DBI::DatabaseError => e puts "An error occurred" puts "Error code: #{e.err}" puts "Error message: #{e.errstr}" dbh.rollback ensure # disconnect from server dbh.disconnect if dbh end
要获取关于脚本在执行过程中执行的操作的调试信息,可以启用跟踪。为此,您必须首先加载dbi / trace模块,然后调用跟踪方式来控制跟踪模式并输出目标 -
require "dbi/trace" .............. trace(mode, destination)
模式值可以为0(关闭),1,2或3,目的地应为IO对象。默认值分别为2和STDERR。
有一些方法可以创建句柄。可以使用代码块调用这些方法。使用代码块和方法的优点是它们将代码块的句柄提供为其参数,并在块终止时自动清除句柄。有几个例子来理解这个概念。
DBI.connect - 此方法生成数据库句柄,建议在块末端调用断开连接以断开数据库连接。
dbh.prepare - 此方法生成语句句柄,建议在块结束时完成。在块内,您必须调用execute方法来执行该语句。
dbh.execute - 这个方法是相似的,除了我们不需要在块内调用execute。语句句柄自动执行。
DBI.connect可以采取代码块,将数据库句柄传递给它,并自动断开块末尾的句柄,如下所示。
dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123") do |dbh|
dbh.prepare可以采取代码块,将语句句柄传递给它,并在块的结尾自动调用finish,如下所示。
dbh.prepare("SHOW DATABASES") do |sth| sth.execute puts "Databases: " + sth.fetch_all.join(", ") end
dbh.execute可以采取代码块,将语句句柄传递给它,并在块的结尾自动调用finish,如下所示:
dbh.execute("SHOW DATABASES") do |sth| puts "Databases: " + sth.fetch_all.join(", ") end
DBI 事务方法也采用上面已经描述的代码块。
DBI允许数据库驱动程序提供额外的特定于数据库的功能,用户可以通过任何Handle对象的func方法调用该函数。
支持特定于驱动程序的属性,可以使用[] =或[]方法进行设置或获取。
#!/usr/bin/ruby require "dbi" begin # connect to the MySQL server dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123") puts dbh.func(:client_info) puts dbh.func(:client_version) puts dbh.func(:host_info) puts dbh.func(:proto_info) puts dbh.func(:server_info) puts dbh.func(:thread_id) puts dbh.func(:stat) rescue DBI::DatabaseError => e puts "An error occurred" puts "Error code: #{e.err}" puts "Error message: #{e.errstr}" ensure dbh.disconnect if dbh end
输出结果如下 -
5.0.45 50045 Localhost via UNIX socket 10 5.0.45 150621 Uptime: 384981 Threads: 1 Questions: 1101078 Slow queries: 4 Opens: 324 Flush tables: 1 Open tables: 64 Queries per second avg: 2.860
Ruby是一种通用语言; 它根本不能被称为网络语言。即使如此,一般来说,Web应用程序和Web工具是Ruby最常用的功能之一。
您不仅可以在Ruby中编写自己的SMTP服务器,FTP守护程序或Web服务器,还可以使用Ruby进行更常用的工作,如CGI编程或替代PHP。
请使用CGI编程教程花费几分钟时间了解CGI编程的更多细节。
最基本的Ruby CGI脚本看起来像这样 -
#!/usr/bin/ruby puts "HTTP/1.0 200 OK" puts "Content-type: text/html " puts "<html><body>This is a test</body></html>"
如果您调用此脚本test.cgi并将其上传到具有正确权限的基于Unix的Web托管服务提供商,则可以将其用作CGI脚本。
例如,如果您使用网站https://www.example.com/托管一个Linux Web托管服务提供商,并将test.cgi上传到主目录并赋予其执行权限,然后访问https:// www。 example.com/test.cgi应该返回一个HTML页面,说这是一个测试。
这里当从Web浏览器请求test.cgi时,Web服务器在Web站点上查找test.cgi,然后使用Ruby解释器执行。Ruby脚本返回一个基本的HTTP头,然后返回一个基本的HTML文档。
Ruby提供了一个名为cgi的特殊库,可以实现比上一个CGI脚本更复杂的交互。
让我们创建一个使用cgi的基本CGI脚本 -
#!/usr/bin/ruby require "cgi" cgi = CGI.new puts cgi.header puts "<html><body>This is a test</body></html>"
在这里,您创建了一个CGI对象,并使用它来为您打印标题行。
使用类CGI可以通过两种方式访问HTML查询参数。假设我们给了一个URL /cgi-bin/test.cgi?FirstName = Zara&LastName = Ali。
您可以直接使用CGI#[] 访问参数FirstName和LastName,如下所示:
#!/usr/bin/ruby require "cgi" cgi = CGI.new cgi["FirstName"] # => ["Zara"] cgi["LastName"] # => ["Ali"]
有另一种访问这些表单变量的方法。这个代码将给你一个哈希的所有键和值 -
#!/usr/bin/ruby require "cgi" cgi = CGI.new h = cgi.params # => {"FirstName"=>["Zara"],"LastName"=>["Ali"]} h["FirstName"] # => ["Zara"] h["LastName"] # => ["Ali"]
以下是检索所有密钥的代码 -
#!/usr/bin/ruby require "cgi" cgi = CGI.new cgi.keys # => ["FirstName", "LastName"]
如果表单包含多个具有相同名称的字段,则相应的值将作为数组返回到脚本。[]访问器只返回这些中的第一个。指定params方法的结果,以获取它们。
在这个例子中,假设表单有三个字段叫做“name”,我们输入三个名字“Zara”,“Huma”和“Nuha”
#!/usr/bin/ruby require "cgi" cgi = CGI.new cgi["name"] # => "Zara" cgi.params["name"] # => ["Zara", "Huma", "Nuha"] cgi.keys # => ["name"] cgi.params # => {"name"=>["Zara", "Huma", "Nuha"]}
注意 - Ruby将自动处理GET和POST方法。这两种不同的方法没有单独的处理方法。
可以发送正确数据的关联但基本的表单将具有如下所示的HTML代码:
<html> <body> <form method = "POST" action = "http://www.example.com/test.cgi"> First Name :<input type = "text" name = "FirstName" value = "" /> <br /> Last Name :<input type = "text" name = "LastName" value = "" /> <input type = "submit" value = "Submit Data" /> </form> </body> </html>
CGI包含大量用于创建HTML的方法。每个标签可以找到一种方法。为了启用这些方法,您必须通过调用CGI.new创建一个CGI对象。
为了使标签嵌套更容易,这些方法将其内容作为代码块。代码块应该返回一个String,它将被用作标签的内容。例如 -
#!/usr/bin/ruby require "cgi" cgi = CGI.new("html4") cgi.out{ cgi.html{ cgi.head{ " "+cgi.title{"This Is a Test"} } + cgi.body{ " "+ cgi.form{" "+ cgi.hr + cgi.h1 { "A Form: " } + " "+ cgi.textarea("get_text") +" "+ cgi.br + cgi.submit } } } }
注意 - CGI类的表单方法可以接受一个方法参数,它将设置在表单提交中使用的HTTP方法(GET,POST等等)。在此示例中使用的默认值为POST。
输出结果如下 -
Content-Type: text/html Content-Length: 302 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Final//EN"> <HTML> <HEAD> <TITLE>This Is a Test</TITLE> </HEAD> <BODY> <FORM METHOD = "post" ENCTYPE = "application/x-www-form-urlencoded"> <HR> <H1>A Form: </H1> <TEXTAREA COLS = "70" NAME = "get_text" ROWS = "10"></TEXTAREA> <BR> <INPUT TYPE = "submit"> </FORM> </BODY> </HTML>
处理URL和HTML代码时,必须小心引用某些字符。例如,斜杠字符(/)在URL中具有特殊含义,因此如果它不是路径名的一部分,则必须进行转义。
例如,URL中的任何/在查询部分将被转换为字符string%2F,并且必须翻译成/使用它。空间和符号也是特殊字符。为了处理这个问题,CGI提供了例程CGI.escape和 CGI.unescape。
#!/usr/bin/ruby require "cgi" puts CGI.escape(Zara Ali/A Sweet & Sour Girl")
输出结果如下 -
Zara+Ali%2FA Sweet+%26+Sour+Girl")
#!/usr/bin/ruby require "cgi" puts CGI.escapeHTML("<h1>Zara Ali/A Sweet & Sour Girl</h1>")
输出结果如下 -
<h1>Zara Ali/A Sweet & Sour Girl</h1>"
以下是与CGI类相关的方法列表 -
在Ruby的CGI -相关标准CGI库方法。
我们已经在不同的部分解释了这两个概念。请按照这些部分 -
在Ruby的CGIcookie -如何处理CGIcookie。
在Ruby的CGI会议 -如何管理CGI会话。
您可以在互联网上查看以下主题,在基于Unix的服务器上托管您的网站 -
简单邮件传输协议(SMTP)是一种协议,用于在邮件服务器之间发送电子邮件和路由电子邮件。
Ruby为简单邮件传输协议(SMTP)客户端连接提供了Net :: SMTP类,并提供了两种类新方法和开始。
在新的有两个参数-
启动方法将这些参数-
该服务器 - SMTP服务器的IP名,默认为本地主机。
该端口 -端口号,默认为25。
的域 -邮件发件人的域,默认为ENV [“HOSTNAME”]。
该帐户 -用户名,默认值是零。
该密码 -用户密码,默认为无。
该authType的 -授权类型,默认为cram_md5。
SMTP对象具有称为sendmail的实例方法,通常用于执行邮件邮件的工作。它需要三个参数 -
的源 -一个字符string或数组或用任何每个迭代一次返回一个字符string。
该发送者 -将在出现的字符string从电子邮件的范围。
收件人 - 表示收件人收件人的字符string或字符string数组。
这是使用Ruby脚本发送一封电子邮件的简单方法。尝试一次 -
require "net/smtp" message = <<MESSAGE_END From: Private Person <me@fromdomain.com> To: A Test User <test@todomain.com> Subject: SMTP e-mail test This is a test e-mail message. MESSAGE_END Net::SMTP.start("localhost") do |smtp| smtp.send_message message, "me@fromdomain.com", "test@todomain.com" end
在这里,您已经在邮件中放置了基本的电子邮件,使用文档,请注意正确格式化标题。电子邮件需要一个From,To和Subject标题,与电子邮件正文分开,空行。
要发送邮件,您使用Net :: SMTP连接到本地计算机上的SMTP服务器,然后使用send_message方法以及消息,从地址和目标地址作为参数(即使来自和地址是在电子邮件本身内,这些并不总是用于路由邮件)。
如果您的计算机上没有运行SMTP服务器,则可以使用Net :: SMTP与远程SMTP服务器进行通信。除非您使用Webmail服务(如Hotmail或Yahoo! Mail),否则您的电子邮件提供商将为您提供可以提供给Net :: SMTP的外发邮件服务器详细信息,如下所示:
Net::SMTP.start("mail.your-domain.com")
这行代码连接到mail.your-domain.com的端口25上的SMTP服务器,而不使用任何用户名或密码。但是,如果需要,可以指定端口号和其他详细信息。例如 -
Net::SMTP.start("mail.your-domain.com", 25, "localhost", "username", "password" :plain)
此示例使用纯文本格式的用户名和密码在mail.your-domain.com上连接到SMTP服务器。它将客户端的主机名标识为localhost。
当您使用Ruby发送短信时,所有内容将被视为简单文本。即使您将文本消息中包含HTML标签,它将显示为简单文本,HTML标签将不会根据HTML语法进行格式化。但是,Ruby Net :: SMTP提供了将HTML消息作为HTML消息发送的选项。
发送电子邮件时,您可以指定一个Mime版本,内容类型和字符集来发送HTML电子邮件。
以邮件形式发送HTML内容的例子如下。尝试一次 -
require "net/smtp" message = <<MESSAGE_END From: Private Person <me@fromdomain.com> To: A Test User <test@todomain.com> MIME-Version: 1.0 Content-type: text/html Subject: SMTP e-mail test This is an e-mail message to be sent in HTML format <b>This is HTML message.</b> <h1>This is headline.</h1> MESSAGE_END Net::SMTP.start("localhost") do |smtp| smtp.send_message message, "me@fromdomain.com", "test@todomain.com" end
要发送具有混合内容的电子邮件,需要将Content-type标题设置为multipart / mixed。然后可以在边界内指定文本和附件部分。
一个边界以两个连字符开始,后跟一个唯一的号码,不能出现在邮件的邮件部分。表示电子邮件最终部分的最后一个边界也必须以两个连字符结尾。
使用pack(“m”)函数对附加文件进行编码,以便在传输之前具有base64编码。
以下是以附件形式发送/tmp/test.txt文件的示例。
require "net/smtp" filename = "/tmp/test.txt" # Read a file and encode it into base64 format filecontent = File.read(filename) encodedcontent = [filecontent].pack("m") # base64 marker = "AUNIQUEMARKER" body = <<EOF This is a test email to send an attachement. EOF # Define the main headers. part1 = <<EOF From: Private Person <me@fromdomain.net> To: A Test User <test@todmain.com> Subject: Sending Attachement MIME-Version: 1.0 Content-Type: multipart/mixed; boundary = #{marker} --#{marker} EOF # Define the message action part2 = <<EOF Content-Type: text/plain Content-Transfer-Encoding:8bit #{body} --#{marker} EOF # Define the attachment section part3 = <<EOF Content-Type: multipart/mixed; name = "#{filename}" Content-Transfer-Encoding:base64 Content-Disposition: attachment; filename = "#{filename}" #{encodedcontent} --#{marker}-- EOF mailtext = part1 + part2 + part3 # Let"s put our code in safe area begin Net::SMTP.start("localhost") do |smtp| smtp.sendmail(mailtext, "me@fromdomain.net", ["test@todmain.com"]) end rescue Exception => e print "Exception occured: " + e end
注意 - 您可以在数组中指定多个目的地,但应以逗号分隔。
Ruby提供两级访问网络服务。在低级别,您可以访问底层操作系统中的基本套接字支持,这允许您为面向连接和无连接协议实现客户端和服务器。
Ruby还具有提供对特定应用级网络协议(如FTP,HTTP等)的更高级别访问的库。
本章让您了解网络中最着名的概念 - 套接字编程。
套接字是双向通信通道的端点。套接字可以在一个进程内,在同一机器上的进程之间,或者在不同大陆的进程之间进行通信。
套接字可以通过多种不同的通道类型实现:Unix域套接字,TCP,UDP等。该插座提供特定的类来处理常见的传输以及用于处理其余的通用接口。
插座有自己的词汇 -
没有 | 期限和描述 |
---|---|
1 | 域
将用作运输机制的协议族。这些值是常量,例如PF_INET,PF_UNIX,PF_X25等。 |
2 | 类型
两个端点之间的通信类型,通常用于面向连接的协议的SOCK_STREAM和用于无连接协议的SOCK_DGRAM。 |
3 | 协议
通常为零,这可以用于标识域和类型中的协议的变体。 |
4 | 主机名
网络接口的标识符 - 一个字符string,可以是一个主机名,一个点四分之一地址,或一个冒号中的IPV6地址(可能是点)符号 一个字符string“<广播>”,它指定一个INADDR_BROADCAST地址。 一个零长度的字符string,指定INADDR_ANY,或 整数,以主机字节顺序解释为二进制地址。 |
5 | 港口
每个服务器监听呼叫一个或多个端口的客户端。端口可能是Fixnum端口号,包含端口号的字符string或服务名称。 |
这里我们将编写一个非常简单的客户端程序,它将打开一个给定端口和给定主机的连接。Ruby类的TCPSocket提供打开这样一个socket的开放功能。
TCPSocket.open(hosname,端口)打开一个TCP连接到主机上的端口。
一旦您打开了一个套接字,就可以像任何IO对象一样读取它。完成后,请记住关闭它,就像关闭文件一样。
以下代码是一个非常简单的客户端,连接到给定的主机和端口,从套接字读取任何可用的数据,然后退出 -
require "socket" # Sockets are in standard library hostname = "localhost" port = 2000 s = TCPSocket.open(hostname, port) while line = s.gets # Read lines from the socket puts line.chop # And print with platform line terminator end s.close # Close the socket when done
要编写Internet服务器,我们使用TCPServer类。TCPServer对象是TCPSocket对象的工厂。
现在调用TCPServer.open(hostname,port函数)为您的服务指定一个端口并创建一个TCPServer对象。
接下来,调用返回的TCPServer对象的accept方法。此方法等待直到客户端连接到您指定的端口,然后返回表示到该客户端的连接的TCPSocket对象。
require "socket" # Get sockets from stdlib server = TCPServer.open(2000) # Socket to listen on port 2000 loop { # Servers run forever client = server.accept # Wait for a client to connect client.puts(Time.now.ctime) # Send the time to the client client.puts "Closing the connection. Bye!" client.close # Disconnect from the client }
现在,在后台运行这个服务器,然后运行上面的客户端来查看结果。
互联网上的大多数服务器都是随时处理大量客户端的。
Ruby的Thread类可以轻松创建一个接受请求的多线程服务器,并立即创建一个新的执行线程来处理连接,同时允许主程序等待更多的连接 -
require "socket" # Get sockets from stdlib server = TCPServer.open(2000) # Socket to listen on port 2000 loop { # Servers run forever Thread.start(server.accept) do |client| client.puts(Time.now.ctime) # Send the time to the client client.puts "Closing the connection. Bye!" client.close # Disconnect from the client end }
在此示例中,您有一个永久循环,当server.accept响应时,将创建一个新线程并立即启动,以使用传入线程的连接对象立即处理刚被接受的连接。然而,主程序立即循环并等待新的连接。
以这种方式使用Ruby线程意味着代码是可移植的,并且将以相同的方式在Linux,OS X和Windows上运行。
我们可以使用套接字库实现任何Internet协议。这里,例如,是用于获取网页内容的代码 -
require "socket" host = "www.tutorialspoint.com" # The web server port = 80 # Default HTTP port path = "/index.htm" # The file we want # This is the HTTP request we send to fetch a file request = "GET #{path} HTTP/1.0 " socket = TCPSocket.open(host,port) # Connect to server socket.print(request) # Send request response = socket.read # Read complete response # Split response at first blank line into headers and body headers,body = response.split(" ", 2) print body # And display it
要实现类似的Web客户端,您可以使用预创建的库,如Net :: HTTP来处理HTTP。以下代码与前面的代码相当 -
require "net/http" # The library we need host = "www.tutorialspoint.com" # The web server path = "/index.htm" # The file we want http = Net::HTTP.new(host) # Create a connection headers, body = http.get(path) # Request the file if headers.code == "200" # Check the status code print body else puts "#{headers.code} #{headers.message}" end
请检查类似的库以使用FTP,SMTP,POP和IMAP协议。
我们已经给你一个快速启动套接字编程。这是一个很大的主题,所以建议您通过Ruby Socket Library和Class Methods来查找更多详细信息。
可扩展标记语言(XML)是一种非常像HTML或SGML的标记语言。这是由万维网联盟推荐并作为开放标准提供的。
XML是一种便携式的开源语言,允许程序员开发可由其他应用程序读取的应用程序,无论操作系统和/或开发语言如何。
XML对于跟踪小到中等数量的数据非常有用,而不需要基于SQL的主干。
XML解析器有两种不同的风格:
SAX类(Stream接口) - 在此处注册感兴趣的事件的回调,然后让解析器继续执行文档。当您的文档较大或内存有限,在从文件读取文件时解析文件,并且整个文件不会存储在内存中,这很有用。
DOM类(对象树接口) - 这是万维网联盟推荐,其中将整个文件读入内存并以分层(基于树)的形式存储,以表示XML文档的所有功能。
当处理大文件时,SAX显然无法像DOM那样快速处理信息。另一方面,使用DOM专门可以真正地杀死你的资源,特别是如果用在很多小文件上。
SAX是只读的,而DOM允许更改XML文件。由于这两个不同的API互相补充,所以没有理由不能将它们用于大型项目。
操作XML的最常见方法是使用Sean Russell的REXML库。自2002年以来,REXML已经成为标准Ruby发行版的一部分。
REXML是符合XML 1.0标准的纯Ruby XML处理器。它是一个非验证的处理器,通过了所有的OASIS非验证一致性测试。
REXML解析器比其他可用的解析器具有以下优点 -
对于我们所有的XML代码示例,让我们使用一个简单的XML文件作为输入 -
<collection shelf = "New Arrivals"> <movie title = "Enemy Behind"> <type>War, Thriller</type> <format>DVD</format> <year>2003</year> <rating>PG</rating> <stars>10</stars> <description>Talk about a US-Japan war</description> </movie> <movie title = "Transformers"> <type>Anime, Science Fiction</type> <format>DVD</format> <year>1989</year> <rating>R</rating> <stars>8</stars> <description>A schientific fiction</description> </movie> <movie title = "Trigun"> <type>Anime, Action</type> <format>DVD</format> <episodes>4</episodes> <rating>PG</rating> <stars>10</stars> <description>Vash the Stampede!</description> </movie> <movie title = "Ishtar"> <type>Comedy</type> <format>VHS</format> <rating>PG</rating> <stars>2</stars> <description>Viewable boredom</description> </movie> </collection>
我们首先用树解析我们的XML数据。我们首先要求rexml /文档库; 通常,为了方便起见,我们会将REXML包含进顶级命名空间中。
#!/usr/bin/ruby -w require "rexml/document" include REXML xmlfile = File.new("movies.xml") xmldoc = Document.new(xmlfile) # Now get the root element root = xmldoc.root puts "Root element : " + root.attributes["shelf"] # This will output all the movie titles. xmldoc.elements.each("collection/movie"){ |e| puts "Movie Title : " + e.attributes["title"] } # This will output all the movie types. xmldoc.elements.each("collection/movie/type") { |e| puts "Movie Type : " + e.text } # This will output all the movie description. xmldoc.elements.each("collection/movie/description") { |e| puts "Movie Description : " + e.text }
输出结果如下 -
Root element : New Arrivals Movie Title : Enemy Behind Movie Title : Transformers Movie Title : Trigun Movie Title : Ishtar Movie Type : War, Thriller Movie Type : Anime, Science Fiction Movie Type : Anime, Action Movie Type : Comedy Movie Description : Talk about a US-Japan war Movie Description : A schientific fiction Movie Description : Vash the Stampede! Movie Description : Viewable boredom
要处理相同的数据,movies.xml,以流为导向的方式,我们将定义一个侦听器类,其方法将是解析器的回调目标。
注意 - 不建议对一个小文件使用类似SAX的解析,这只是一个演示示例。
#!/usr/bin/ruby -w require "rexml/document" require "rexml/streamlistener" include REXML class MyListener include REXML::StreamListener def tag_start(*args) puts "tag_start: #{args.map {|x| x.inspect}.join(", ")}" end def text(data) return if data =~ /^w*$/ # whitespace only abbrev = data[0..40] + (data.length > 40 ? "..." : "") puts " text : #{abbrev.inspect}" end end list = MyListener.new xmlfile = File.new("movies.xml") Document.parse_stream(xmlfile, list)
输出结果如下 -
tag_start: "collection", {"shelf"=>"New Arrivals"} tag_start: "movie", {"title"=>"Enemy Behind"} tag_start: "type", {} text : "War, Thriller" tag_start: "format", {} tag_start: "year", {} tag_start: "rating", {} tag_start: "stars", {} tag_start: "description", {} text : "Talk about a US-Japan war" tag_start: "movie", {"title"=>"Transformers"} tag_start: "type", {} text : "Anime, Science Fiction" tag_start: "format", {} tag_start: "year", {} tag_start: "rating", {} tag_start: "stars", {} tag_start: "description", {} text : "A schientific fiction" tag_start: "movie", {"title"=>"Trigun"} tag_start: "type", {} text : "Anime, Action" tag_start: "format", {} tag_start: "episodes", {} tag_start: "rating", {} tag_start: "stars", {} tag_start: "description", {} text : "Vash the Stampede!" tag_start: "movie", {"title"=>"Ishtar"} tag_start: "type", {} tag_start: "format", {} tag_start: "rating", {} tag_start: "stars", {} tag_start: "description", {} text : "Viewable boredom"
查看XML的另一种方法是XPath。这是一种描述如何在XML文档中定位特定元素和属性的伪语言,将该文档视为逻辑有序树。
REXML通过XPath类支持XPath。它假定了基于树的解析(文档对象模型),如上所述。
#!/usr/bin/ruby -w require "rexml/document" include REXML xmlfile = File.new("movies.xml") xmldoc = Document.new(xmlfile) # Info for the first movie found movie = XPath.first(xmldoc, "//movie") p movie # Print out all the movie types XPath.each(xmldoc, "//type") { |e| puts e.text } # Get an array of all of the movie formats. names = XPath.match(xmldoc, "//format").map {|x| x.text } p names
输出结果如下 -
<movie title = "Enemy Behind"> ... </> War, Thriller Anime, Science Fiction Anime, Action Comedy ["DVD", "DVD", "DVD", "VHS"]
Ruby可以使用两种XSLT解析器。这里给出了每个的简要说明。
该解析器由高桥正义写的和维护。这主要用于Linux操作系统,需要以下库 -
你可以在Ruby-Sablotron找到这个模块。
XSLT4R由Michael Neumann编写,可以在XML部分的RAA中找到。XSLT4R使用简单的命令行界面,尽管它可以替代地在第三方应用程序中使用来转换XML文档。
XSLT4R需要XMLScan进行操作,这包括在XSLT4R存档中,也是一个100%的Ruby模块。这些模块可以使用标准的Ruby安装方法安装(即ruby install.rb)。
XSLT4R具有以下语法 -
ruby xslt.rb stylesheet.xsl document.xml [arguments]
如果要在应用程序中使用XSLT4R,可以包括XSLT并输入所需的参数。这是例子 -
require "xslt" stylesheet = File.readlines("stylesheet.xsl").to_s xml_doc = File.readlines("document.xml").to_s arguments = { "image_dir" => "/...." } sheet = XSLT::Stylesheet.new( stylesheet, arguments ) # output to StdOut sheet.apply( xml_doc ) # output to "str" str = "" sheet.output = [ str ] sheet.apply( xml_doc )
有关REXML解析器的完整详细信息,请参阅REXML解析器文档的标准文档。
您可以从RAA Repository下载XSLT4R。
简单对象访问协议(SOAP)是一种跨平台和语言无关的基于XML的RPC协议,通常(但不一定)HTTP。
它使用XML对远程过程调用的信息进行编码,并将HTTP通过网络从客户端传输到服务器,反之亦然。
SOAP比其他技术(如COM,CORBA等)具有以下优点:例如,其相对便宜的部署和调试成本,其可扩展性和易用性以及针对不同语言和平台的多种实现方式的存在。
请参阅我们的简单教程SOAP来详细了解它。
本章使您熟悉Ruby(SOAP4R)的SOAP实现。这是一个基本的教程,所以如果你需要一个深刻的细节,你需要引用其他资源。
SOAP4R是由Hiroshi Nakamura开发的Ruby的SOAP实现,可以从 -
注意 - 可能很有可能您已经安装了此组件。
Download SOAP
如果您知道gem实用程序,则可以使用以下命令安装SOAP4R和相关软件包。
$ gem install soap4r --include-dependencies
如果您在Windows上工作,则需要从上述位置下载压缩文件,并且需要使用标准安装方法通过运行ruby install.rb进行安装。
SOAP4R支持两种不同类型的服务器 -
基于CGI / FastCGI(SOAP :: RPC :: CGIStub)
独立(SOAP :: RPC:StandaloneServer)
本章详细介绍了独立服务器的编写。编写SOAP服务器时涉及以下步骤。
要实现自己的独立服务器,您需要编写一个新类,这将是SOAP :: StandaloneServer的子代,如下所示:
class MyServer < SOAP::RPC::StandaloneServer ............... end
注意 - 如果要编写基于FastCGI的服务器,则需要将SOAP :: RPC :: CGIStub作为父类,其余的过程将保持不变。
第二步是编写您想要向外界公开的Web服务方法。
它们可以写成简单的Ruby方法。例如,我们来写两个方法来添加两个数字并划分两个数字 -
class MyServer < SOAP::RPC::StandaloneServer ............... # Handler methods def add(a, b) return a + b end def div(a, b) return a / b end end
下一步是将我们定义的方法添加到我们的服务器。所述初始化方法用于暴露服务的方法与以下两种方法之一-
class MyServer < SOAP::RPC::StandaloneServer def initialize(*args) add_method(receiver, methodName, *paramArg) end end
这是参数的描述 -
没有 | 参数说明 |
---|---|
1 | 接收器
包含methodName方法的对象。您将定义与methodDef方法在同一类中的服务方法,此参数为self。 |
2 | methodName
由于RPC请求而调用的方法的名称。 |
3 | 参数
指定参数名称和参数模式。 |
要了解inout或out参数的用法,请考虑以下服务方法,它使用两个参数(inParam和inoutParam),返回一个正常的返回值(retVal)和另外两个参数:inoutParam和outParam -
def aMeth(inParam, inoutParam) retVal = inParam + inoutParam outParam = inParam . inoutParam inoutParam = inParam * inoutParam return retVal, inoutParam, outParam end
现在我们可以公开这种方法如下 -
add_method(self, "aMeth", [ %w(in inParam), %w(inout inoutParam), %w(out outParam), %w(retval return) ])
最后一步是通过实例化派生类的一个实例并调用start方法来启动服务器。
myServer = MyServer.new("ServerName", "urn:ruby:ServiceName", hostname, port) myServer.start
以下是所需参数的说明 -
没有 | 参数说明 |
---|---|
1 | 服务器名称
一个服务器名称,你可以给你最喜欢的。 |
2 | urn:ruby:ServiceName
这里urn:ruby是常量,但是您可以为此服务器提供唯一的ServiceName名称。 |
3 | 主机名
指定此服务器将侦听的主机名。 |
4 | 港口
用于Web服务的可用端口号。 |
现在,使用上述步骤,让我们写一个独立的服务器 -
require "soap/rpc/standaloneserver" begin class MyServer < SOAP::RPC::StandaloneServer # Expose our services def initialize(*args) add_method(self, "add", "a", "b") add_method(self, "div", "a", "b") end # Handler methods def add(a, b) return a + b end def div(a, b) return a / b end end server = MyServer.new("MyServer", "urn:ruby:calculation", "localhost", 8080) trap("INT){ server.shutdown } server.start rescue => err puts err.message end
执行时,该服务器应用程序启动上一个独立的SOAP服务器本地主机并侦听请求的端口 8080。它暴露了一个服务方法,添加和DIV,它有两个参数,并返回结果。
现在,您可以在后台运行此服务器,如下所示:
$ ruby MyServer.rb&
该SOAP RPC :: ::驱动程序类为编写SOAP客户端应用程序的支持。本章介绍了这个类,并在应用的基础上演示了它的用法。
以下是您需要调用SOAP服务的最低限度信息 -
现在,我们将编写一个SOAP客户端,它将调用上面例子中定义的名为add和div的服务方法。
以下是创建SOAP客户端的主要步骤。
我们通过调用其新方法创建一个SOAP :: RPC :: Driver的实例,如下所示:
SOAP::RPC::Driver.new(endPoint, nameSpace, soapAction)
以下是所需参数的说明 -
没有 | 参数说明 |
---|---|
1 | endPoint
要连接的SOAP服务器的URL。 |
2 | nameSpace
用于使用此SOAP :: RPC :: Driver对象的所有RPC的命名空间。 |
3 | soapAction
HTTP标头的SOAPAction字段的值。如果nil默认为空字符string“”。 |
要将SOAP服务方法添加到SOAP :: RPC :: Driver中,我们可以使用SOAP :: RPC :: Driver实例调用以下方法:
driver.add_method(name, *paramArg)
这是参数的描述 -
没有 | 参数说明 |
---|---|
1 | name
远程Web服务方法的名称。 |
2 | 参数
指定远程过程参数的名称。 |
最后一步是使用SOAP :: RPC :: Driver实例发送SOAP服务,如下所示:
result = driver.serviceMethod(paramArg...)
这里serviceMethod是实际的Web服务方法,paramArg ...是传递服务方法所需的列表参数。
基于上述步骤,我们将编写一个SOAP客户端,如下所示:
#!/usr/bin/ruby -w require "soap/rpc/driver" NAMESPACE = "urn:ruby:calculation" URL = "http://localhost:8080/" begin driver = SOAP::RPC::Driver.new(URL, NAMESPACE) # Add remote sevice methods driver.add_method("add", "a", "b") # Call remote service methods puts driver.add(20, 30) rescue => err puts err.message end
我已经用Ruby解释了Web服务的基本概念。如果您想进一步深入了解,那么有以下链接可以使用Ruby查找有关Web服务的更多详细信息。
Ruby的标准图形用户界面(GUI)是Tk。Tk开始是由John Ousterhout开发的Tcl脚本语言的GUI。
Tk具有独特的区别,成为唯一的跨平台GUI。Tk在Windows,Mac和Linux上运行,并在每个操作系统上提供了原生的外观。
基于Tk的应用程序的基本组件称为小部件。组件有时也称为窗口,因为在Tk中,“窗口”和“窗口小部件”通常可互换使用。
Tk应用程序遵循一个小部件层次结构,其中任何数量的小部件可以放置在另一个小部件中,而另一个小部件中的这些小部件则无限制。Tk程序中的主窗口小部件称为根小部件,可以通过创建TkRoot类的新实例来创建。
大多数基于Tk的应用程序都遵循相同的周期:创建窗口小部件,将它们放在界面中,最后将与每个窗口小部件关联的事件绑定到一个方法。
有三个几何管理者 位置,网格和包,负责控制界面中每个窗口小部件的大小和位置。
Ruby Tk绑定是用Ruby分发的,但是Tk是一个单独的安装。Windows用户可以从ActiveState的ActiveTcl下载单击Tk 安装。
Mac和Linux用户可能不需要安装它,因为它已经与操作系统一起安装了很多机会,但如果没有安装,则可以下载预创建的软件包或从Tcl Developer Xchange获取源代码。
Ruby / Tk程序的典型结构是创建主窗口或根窗口(TkRoot的一个实例),向其添加小部件以创建用户界面,然后通过调用Tk.mainloop启动主事件循环。
传统的Hello World!Ruby / Tk的例子看起来像这样 -
require "tk" root = TkRoot.new { title "Hello, World!" } TkLabel.new(root) do text "Hello, World!" pack { padx 15 ; pady 15; side "left" } end Tk.mainloop
这里,加载tk扩展模块后,我们使用TkRoot.new创建一个根级别的框架。然后,我们将一个TkLabel小部件作为根框架的小孩,为标签设置几个选项。最后,我们打包根框架并进入主GUI事件循环。
如果你运行这个脚本,它输出结果如下-
有各种Ruby / Tk类的列表,可用于使用Ruby / Tk创建所需的GUI。
TkFrame创建和操作框架小部件。
TkButton创建和操作按钮小部件。
TkLabel创建和操作标签小部件。
TkEntry创建和操作条目窗口小部件。
TkCheckButton创建和操作检查窗口小部件。
TkRadioButton创建和操作单选按钮小部件。
TkListbox创建和操作列表框小部件。
TkComboBox创建和操作列表框小部件。
TkMenu创建和操作菜单小部件。
TkMenubutton创建和操纵menubutton小部件。
Tk.messageBox创建和操作消息对话框。
TkScrollbar创建和操作滚动条小部件。
TkCanvas创建和操作画布小部件。
TkScale创建和操作缩放小部件。
TkText创建和操作文本小部件。
TkToplevel创建和操作toplevel小部件。
TkSpinbox创建和操作Spinbox小部件。
TkProgressBar创建和操作进度条小部件。
对话框创建和操作对话框小部件。
Tk :: Tile :: Notebook在有限的空间中显示几个窗口与笔记本隐喻。
Tk :: Tile :: Paned显示一些子窗口,垂直或水平堆叠。
Tk :: Tile :: Separator显示水平或垂直分隔条。
Ruby / Tk字体,颜色和图像了解Ruby / Tk字体,颜色和图像
所有窗口小部件都有许多不同的配置选项,通常可以控制它们的显示方式以及它们的行为。当然可用的选项取决于小部件类。
以下是所有标准配置选项的列表,可用于任何Ruby / Tk小部件。
几何管理根据要求处理不同的小部件。Tk中的几何管理依赖于主和从属小部件的概念。
主人是一个小部件,通常是一个顶级窗口或一个框架,它将包含其他小部件,这些小部件被称为从属。您可以将几何管理器视为控制主窗口小部件,并决定将显示哪些内容。
几何管理器将要求每个从属窗口小部件的自然尺寸,或者最理想地显示多大。然后,当它要求几何管理器管理特定的从属窗口小部件时,它将该信息与程序提供的任何参数相结合。
有三个几何管理员放置,网格和包,负责控制界面中每个窗口小部件的大小和位置。
Ruby / Tk支持事件循环,它从操作系统接收事件。这些是按钮按下,按键,鼠标移动,窗口调整大小等等。
Ruby / Tk负责为您管理此事件循环。它会确定事件适用的窗口小部件(用户是否点击此按钮?如果按下一个键,哪个文本框有焦点?),并相应地进行调度。各个小部件知道如何响应事件,例如,当鼠标移动时,按钮可能会更改颜色,并在鼠标离开时还原。
在更高层次上,Ruby / Tk在您的程序中调用回调,以表明widget的重要性。对于任一情况,您都可以提供代码块或Ruby Proc对象,该对象指定应用程序如何响应事件或回调。
我们来看看如何使用bind方法将基本窗口系统事件与处理它们的Ruby过程相关联。绑定的最简单形式作为其输入,指示事件名称的字符string和Tk用于处理事件的代码块。
例如,要抓住ButtonRelease事件在某个小部件上的第一个鼠标按钮,你会写 -
someWidget.bind("ButtonRelease-1") { ....code block to handle this event... }
事件名称可以包括其他修饰符和细节。修饰符是一个像Shift,Control或Alt这样的字符string,表示其中一个修饰键被按下。
所以,例如,抓住当用户按住Ctrl键并单击鼠标右键时生成的事件。
someWidget.bind("Control-ButtonPress-3", proc { puts "Ouch!" })
很多的Ruby / Tk部件可以触发回调当用户激活它们,你可以使用命令回调到指定是发生在某代码块或程序被调用。如前所述,您可以在创建窗口小部件时指定命令回调过程 -
helpButton = TkButton.new(buttonFrame) { text "Help" command proc { showHelp } }
或者您可以稍后使用小部件的命令方法进行分配-
helpButton.command proc { showHelp }
由于命令方法接受过程或代码块,您还可以将以前的代码示例写为 -
helpButton = TkButton.new(buttonFrame) { text "Help" command { showHelp } }
的配置方法可以用来设置和检索的任何小窗口配置的值。例如,要更改按钮的宽度,您可以随时调用configure方法,如下所示:
require "tk" button = TkButton.new { text "Hello World!" pack } button.configure("activebackground", "blue") Tk.mainloop
要获取当前窗口小部件的值,只需提供如下的值即可:
color = button.configure("activebackground")
您也可以调用configure,而不需要任何选项,这将为您提供所有选项及其值的列表。
为了简单地检索选项的值,configure将返回比您通常想要的更多信息。cget方法只返回当前值。
color = button.cget("activebackground")
Ruby / LDAP是Ruby的扩展库。它提供了一些LDAP库的接口,如OpenLDAP,UMich LDAP,Netscape SDK,ActiveDirectory。
用于应用程序开发的通用API在RFC1823中描述,并由Ruby / LDAP支持。
您可以从SOURCEFORGE.NET下载并安装完整的Ruby / LDAP软件包。
在安装Ruby / LDAP之前,请确保您具有以下组件 -
现在,您可以使用标准的Ruby安装方法。在开始之前,如果您想查看extconf.rb的可用选项,请使用“--help”选项运行它。
$ ruby extconf.rb [--with-openldap1|--with-openldap2| --with-netscape|--with-wldap32] $ make $ make install
注 - 如果您在Windows上创建软件,则可能需要使用nmake而不是make。
这是一个两步的过程 -
以下是创建到LDAP目录的连接的语法。
LDAP::Conn.new(host = "localhost", port = LDAP_PORT)
主机 - 这是运行LDAP目录的主机ID。我们会把它当作localhost。
端口 - 这是用于LDAP服务的端口。标准的LDAP端口是636和389.确保服务器上正在使用哪个端口,否则可以使用LDAP :: LDAP_PORT。
该调用返回一个新的LDAP ::康恩连接到服务器,主机,端口的端口。
这是我们通常指定用于会话剩余部分的用户名和密码的地方。
以下是绑定LDAP连接的语法,使用DN,dn,凭据,pwd和bind方法,方法 -
conn.bind(dn = nil, password = nil, method = LDAP::LDAP_AUTH_SIMPLE)do .... end
您可以使用相同的方法而不使用代码块。在这种情况下,您需要如下解释绑定连接:
conn.bind(dn = nil, password = nil, method = LDAP::LDAP_AUTH_SIMPLE) .... conn.unbind
如果给出了一个代码块,则自动被赋予块。
我们现在可以执行搜索,添加,修改或删除绑定方法(bind和unbind)之间的操作,只要我们有适当的权限。
假设我们正在本地服务器上工作,我们可以把它们放在一起,使用适当的主机,域,用户ID和密码等。
#/usr/bin/ruby -w require "ldap" $HOST = "localhost" $PORT = LDAP::LDAP_PORT $SSLPORT = LDAP::LDAPS_PORT conn = LDAP::Conn.new($HOST, $PORT) conn.bind("cn = root, dc = localhost, dc = localdomain","secret") .... conn.unbind
添加LDPA条目是一个两步过程 -
我们需要LDAP :: Mod对象传递给conn.add方法来创建一个条目。以下是创建LDAP :: Mod对象的简单语法-
Mod.new(mod_type, attr, vals)
mod_type - 一个或多个选项LDAP_MOD_ADD,LDAP_MOD_REPLACE或LDAP_MOD_DELETE。
attr - 应该是要操作的属性的名称。
vals - 是与attr有关的一系列值。如果vals包含二进制数据,则mod_type应该与LDAP_MOD_BVALUES在逻辑上是OR(“)。
此调用返回LDAP :: Mod对象,可以传递给LDAP :: Conn类中的方法,如Conn#add,Conn#add_ext,Conn#modify和Conn#modify_ext。
一旦我们准备好使用LDAP :: Mod对象,我们可以调用conn.add方法来创建一个条目。这是一个调用此方法的语法 -
conn.add(dn, attrs)
此方法添加一个包含DN,dn和属性attrs的条目。这里,attrs应该是LDAP :: Mod对象的数组或属性/值数组对的哈希。
这是一个完整的例子,它将创建两个目录项 -
#/usr/bin/ruby -w require "ldap" $HOST = "localhost" $PORT = LDAP::LDAP_PORT $SSLPORT = LDAP::LDAPS_PORT conn = LDAP::Conn.new($HOST, $PORT) conn.bind("cn = root, dc = localhost, dc = localdomain","secret") conn.perror("bind") entry1 = [ LDAP.mod(LDAP::LDAP_MOD_ADD,"objectclass",["top","domain"]), LDAP.mod(LDAP::LDAP_MOD_ADD,"o",["TTSKY.NET"]), LDAP.mod(LDAP::LDAP_MOD_ADD,"dc",["localhost"]), ] entry2 = [ LDAP.mod(LDAP::LDAP_MOD_ADD,"objectclass",["top","person"]), LDAP.mod(LDAP::LDAP_MOD_ADD, "cn", ["Zara Ali"]), LDAP.mod(LDAP::LDAP_MOD_ADD | LDAP::LDAP_MOD_BVALUES, "sn", ["ttate","ALI", "zero 00zero"]), ] begin conn.add("dc = localhost, dc = localdomain", entry1) conn.add("cn = Zara Ali, dc = localhost, dc = localdomain", entry2) rescue LDAP::ResultError conn.perror("add") exit end conn.perror("add") conn.unbind
修改条目与添加条目类似。只需调用modify方法,而不是添加要修改的属性。这是一个简单的修改方法语法。
conn.modify(dn, mods)
此方法修改具有DN,dn和属性mod的条目。这里,mods应该是LDAP :: Mod对象的数组或属性/值数组对的散列。
要修改我们在上一节中添加的条目的姓氏,我们将写 -
#/usr/bin/ruby -w require "ldap" $HOST = "localhost" $PORT = LDAP::LDAP_PORT $SSLPORT = LDAP::LDAPS_PORT conn = LDAP::Conn.new($HOST, $PORT) conn.bind("cn = root, dc = localhost, dc = localdomain","secret") conn.perror("bind") entry1 = [ LDAP.mod(LDAP::LDAP_MOD_REPLACE, "sn", ["Mohtashim"]), ] begin conn.modify("cn = Zara Ali, dc = localhost, dc = localdomain", entry1) rescue LDAP::ResultError conn.perror("modify") exit end conn.perror("modify") conn.unbind
要删除一个条目,请调用具有可分辨名称的delete方法作为参数。这是一个简单的delete方法的语法。
conn.delete(dn)
此方法将删除具有DN,dn的条目。
要删除我们在上一节中添加的Zara Mohtashim条目,我们将写 -
#/usr/bin/ruby -w require "ldap" $HOST = "localhost" $PORT = LDAP::LDAP_PORT $SSLPORT = LDAP::LDAPS_PORT conn = LDAP::Conn.new($HOST, $PORT) conn.bind("cn = root, dc = localhost, dc = localdomain","secret") conn.perror("bind") begin conn.delete("cn = Zara-Mohtashim, dc = localhost, dc = localdomain") rescue LDAP::ResultError conn.perror("delete") exit end conn.perror("delete") conn.unbind
使用modify方法修改条目的可分辨名称是不可能的。而是使用modrdn方法。这里是modrdn方法的简单语法-
conn.modrdn(dn, new_rdn, delete_old_rdn)
该方法使用DN,dn修改条目的RDN ,给出新的RDN,new_rdn。如果delete_old_rdn为true,则旧的RDN值将从条目中删除。
假设我们有以下条目 -
dn: cn = Zara Ali,dc = localhost,dc = localdomain cn: Zara Ali sn: Ali objectclass: person
然后,我们可以使用以下代码修改其可分辨名称 -
#/usr/bin/ruby -w require "ldap" $HOST = "localhost" $PORT = LDAP::LDAP_PORT $SSLPORT = LDAP::LDAPS_PORT conn = LDAP::Conn.new($HOST, $PORT) conn.bind("cn = root, dc = localhost, dc = localdomain","secret") conn.perror("bind") begin conn.modrdn("cn = Zara Ali, dc = localhost, dc = localdomain", "cn = Zara Mohtashim", true) rescue LDAP::ResultError conn.perror("modrdn") exit end conn.perror("modrdn") conn.unbind
要在LDAP目录上执行搜索,请使用搜索方法与三种不同的搜索模式之一 -
LDAP_SCOPE_BASEM - 仅搜索基本节点。
LDAP_SCOPE_ONELEVEL - 搜索基本节点的所有childNode。
LDAP_SCOPE_SUBTREE - 搜索包含基本节点的整个子树。
在这里,我们将搜索整个子树的入口dc = localhost,dc = localdomain为个人对象 -
#/usr/bin/ruby -w require "ldap" $HOST = "localhost" $PORT = LDAP::LDAP_PORT $SSLPORT = LDAP::LDAPS_PORT base = "dc = localhost,dc = localdomain" scope = LDAP::LDAP_SCOPE_SUBTREE filter = "(objectclass = person)" attrs = ["sn", "cn"] conn = LDAP::Conn.new($HOST, $PORT) conn.bind("cn = root, dc = localhost, dc = localdomain","secret") conn.perror("bind") begin conn.search(base, scope, filter, attrs) { |entry| # print distinguished name p entry.dn # print all attribute names p entry.attrs # print values of attribute "sn" p entry.vals("sn") # print entry as Hash p entry.to_hash } rescue LDAP::ResultError conn.perror("search") exit end conn.perror("search") conn.unbind
这将为每个匹配的条目调用给定的代码块,其中LDAP条目由LDAP :: Entry类的实例表示。使用搜索的最后一个参数,您可以指定感兴趣的属性,省略所有其他属性。如果您在此处传递零,则所有属性将返回与关系数据库中的“SELECT *”相同。
LDAP :: Entry类的dn方法(get_dn的别名)返回条目的可分辨名称,使用to_hash方法可以获取其属性(包括可分辨名称)的哈希表示。要获取条目属性的列表,请使用attrs方法(get_attributes的别名)。另外,要获取一个特定属性值的列表,请使用vals方法(get_values的别名)。
Ruby / LDAP定义了两个不同的异常类 -
如果发生错误,新的绑定或解除绑定方法会引发LDAP :: Error异常。
在添加,修改,删除或搜索LDAP目录时,会引发LDAP :: ResultError。
有关LDAP方法的完整详细信息,请参阅LDAP文档的标准文档。
传统程序具有单个执行线程:构成程序的语句或指令将依次执行,直到程序终止。
多线程程序有多个执行线程。在每个线程中,语句按顺序执行,但线程本身可以在多核CPU上并行执行。通常在单个CPU机器上,并行实际并行执行多个线程,但是通过交织线程的执行来模拟并行性。
Ruby使用Thread类轻松编写多线程程序。Ruby线程是一种在代码中实现并发性的轻量级和高效的方法。
要启动新线程,只需将一个块与一个调用Thread.new相关联。将创建一个新线程来执行该块中的代码,原始线程将立即从Thread.new返回,并使用下一条语句继续执行 -
# Thread #1 is running here Thread.new { # Thread #2 runs this code } # Thread #1 runs this code
这是一个例子,它显示了我们如何使用多线程的Ruby程序。
#!/usr/bin/ruby def func1 i = 0 while i<=2 puts "func1 at: #{Time.now}" sleep(2) i = i+1 end end def func2 j = 0 while j<=2 puts "func2 at: #{Time.now}" sleep(1) j = j+1 end end puts "Started At #{Time.now}" t1 = Thread.new{func1()} t2 = Thread.new{func2()} t1.join t2.join puts "End at #{Time.now}"
输出结果如下 -
Started At Wed May 14 08:21:54 -0700 2008 func1 at: Wed May 14 08:21:54 -0700 2008 func2 at: Wed May 14 08:21:54 -0700 2008 func2 at: Wed May 14 08:21:55 -0700 2008 func1 at: Wed May 14 08:21:56 -0700 2008 func2 at: Wed May 14 08:21:56 -0700 2008 func1 at: Wed May 14 08:21:58 -0700 2008 End at Wed May 14 08:22:00 -0700 2008
用Thread.new创建一个新的线程。你也可以使用同义词Thread.start和Thread.fork。
创建线程后无需启动线程,当CPU资源可用时,它将自动运行。
Thread类定义了一些在运行时查询和操作线程的方法。线程运行与调用Thread.new相关联的块中的代码,然后它停止运行。
该块中最后一个表达式的值是线程的值,可以通过调用Thread对象的value方法获得。如果线程已经运行到完成,那么值将立即返回线程的值。否则,值方法将阻塞,直到线程完成才返回。
类方法Thread.current返回表示当前线程的Thread对象。这允许线程自己操纵。类方法Thread.main返回表示主线程的Thread对象。这是Ruby程序启动时开始执行的初始线程。
您可以通过调用该线程的Thread.join方法等待一个特定的线程来完成。调用线程将阻塞,直到给定的线程完成。
如果在主线程中引发异常,并且不在任何地方处理,则Ruby解释器将打印一条消息并退出。在线程中,主线程除外,未处理的异常会导致线程停止运行。
如果一个线程牛逼退出,因为未处理的异常,而另一个线程小号呼叫t.join或t.value,则发生在异常牛逼在螺纹凸起小号。
如果Thread.abort_on_exception为false,默认情况下,一个未处理的异常会直接杀死当前线程,其余所有的线程继续运行。
如果您希望任何线程中的任何未处理的异常导致解释器退出,请将类方法Thread.abort_on_exception设置为true。
t = Thread.new { ... } t.abort_on_exception = true
当线程创建时,线程通常可以访问范围内的任何变量。线程块的局部变量是线程本地的,不会共享。
线程类具有一个特殊的功能,可以通过名称创建和访问线程局部变量。你只需要将线程对象看作是一个哈希,使用[] =写入元素,然后使用[]读取它们。
在这个例子中,每个线程使用关键mycount将一个变量count的当前值记录在一个threadlocal变量中。
#!/usr/bin/ruby count = 0 arr = [] 10.times do |i| arr[i] = Thread.new { sleep(rand(0)/10.0) Thread.current["mycount"] = count count += 1 } end arr.each {|t| t.join; print t["mycount"], ", " } puts "count = #{count}"
这产生以下结果 -
8, 0, 3, 7, 2, 1, 6, 5, 4, 9, count = 10
主线程等待子线程完成,然后打印出每个线程捕获的计数值。
影响线程调度的第一个因素是线程优先级:高优先级线程在低优先级线程之前被调度。更准确地说,如果没有较高优先级的线程等待运行,线程将只获得CPU时间。
您可以设置并查询优先级为priority和优先级的Ruby Thread对象的优先级。新创建的线程与创建它的线程的优先级相同。主线程从优先级0开始。
在开始运行之前,没有办法设置线程的优先级。然而,线程可以将其自身的优先级提高或降低为所需的第一个动作。
如果两个线程共享对相同数据的访问,并且至少有一个线程修改该数据,那么您必须特别小心,以确保没有线程可以看到数据处于不一致的状态。这被称为线程排除。
Mutex是一个实现一个简单信号量锁的类,用于互斥某些共享资源。也就是说,只有一个线程可以在给定时间保持锁定。其他线程可能会选择等待锁可用,或者可以简单地选择立即显示错误,指示锁不可用。
通过在互斥体的控制下对共享数据进行所有访问,我们确保一致性和原子操作。让我们来在线运行例子,第一个没有mutax,第二个与mutax -
#!/usr/bin/ruby require "thread" count1 = count2 = 0 difference = 0 counter = Thread.new do loop do count1 += 1 count2 += 1 end end spy = Thread.new do loop do difference += (count1 - count2).abs end end sleep 1 puts "count1 : #{count1}" puts "count2 : #{count2}" puts "difference : #{difference}"
输出结果如下 -
count1 : 1583766 count2 : 1583766 difference : 0
#!/usr/bin/ruby require "thread" mutex = Mutex.new count1 = count2 = 0 difference = 0 counter = Thread.new do loop do mutex.synchronize do count1 += 1 count2 += 1 end end end spy = Thread.new do loop do mutex.synchronize do difference += (count1 - count2).abs end end end sleep 1 mutex.lock puts "count1 : #{count1}" puts "count2 : #{count2}" puts "difference : #{difference}"
输出结果如下 -
count1 : 696591 count2 : 696591 difference : 0
当我们开始使用Mutex对象进行线程排除时,我们必须小心避免死锁。死锁是当所有线程等待获取另一个线程持有的资源时发生的情况。因为所有线程都被阻塞,所以它们不能释放它们所持有的锁。并且因为它们不能释放锁,所以没有其他线程可以获得这些锁。
这就是条件变量的映射。甲条件变量仅仅是一个与资源相关联,并且在特定的保护内使用的信号的互斥。当您需要不可用的资源时,请等待条件变量。该操作释放相应互斥体上的锁定。当一些其他线程发出资源可用时,原始线程脱离等待,同时重新获得关键区域的锁定。
#!/usr/bin/ruby require "thread" mutex = Mutex.new cv = ConditionVariable.new a = Thread.new { mutex.synchronize { puts "A: I have critical section, but will wait for cv" cv.wait(mutex) puts "A: I have critical section again! I rule!" } } puts "(Later, back at the ranch...)" b = Thread.new { mutex.synchronize { puts "B: Now I am critical, but am done with cv" cv.signal puts "B: I am still critical, finishing up" } } a.join b.join
输出结果如下 -
A: I have critical section, but will wait for cv (Later, back at the ranch...) B: Now I am critical, but am done with cv B: I am still critical, finishing up A: I have critical section again! I rule!
有五个可能的返回值对应于五种可能的状态,如下表所示。该状态方法返回线程的状态。
线程状态 | 返回值 |
---|---|
可运行 | 跑 |
睡眠 | 睡眠 |
中止 | 中止 |
正常终止 | false |
终止异常 | 零 |
以下方法由Thread类提供,它们适用于程序中可用的所有线程。这些方法将被称为使用Thread类名,如下所示:
Thread.abort_on_exception = true
这些方法适用于线程的实例。这些方法将被称为使用Thread的一个实例,如下所示:
#!/usr/bin/ruby thr = Thread.new do # Calling a class method new puts "In second thread" raise "Raise exception" end thr.join # Calling an instance method join
由于Object类包含了内核模块,所以Ruby程序中的任何地方都可以使用它的方法。它们可以在没有接收器(功能形式)的情况下被调用。因此,它们通常被称为功能。
以下是与号码相关的内置函数的列表。它们应该如下使用 -
#!/usr/bin/ruby num = 12.40 puts num.floor # 12 puts num + 10 # 22.40 puts num.integer? # false as num is a float.
输出结果如下 -
12 22.4 false
函数sprintf(fmt [,arg ...])和format(fmt [,arg ...])返回一个字符string,其中arg根据fmt进行格式化。格式化规范与C编程语言中的sprintf基本相同。在转换说明(%然后进行转换字段指定符)FMT被相应的参数的格式的字符string替换。
以下是使用示例 -
#!/usr/bin/ruby str = sprintf("%s ", "abc") # => "abc " (simplest form) puts str str = sprintf("d=%d", 42) # => "d=42" (decimal output) puts str str = sprintf("%04x", 255) # => "00ff" (width 4, zero padded) puts str str = sprintf("%8s", "hello") # => " hello" (space padded) puts str str = sprintf("%.2s", "hello") # => "he" (trimmed by precision) puts str
输出结果如下 -
abc d=42 00ff hello he
功能测试(测试中,f1 [,F2])执行由字符指定了以下文件测试之一测试。为了提高可读性,您应该使用File类方法(例如File ::可读?)而不是此函数。
以下是使用示例。假设main.rb存在读,写和不执行权限 -
#!/usr/bin/ruby puts test(?r, "main.rb" ) # => true puts test(?w, "main.rb" ) # => true puts test(?x, "main.rb" ) # => false
输出结果如下 -
true true false
Ruby的预定义变量会影响整个程序的行为,因此不推荐在库中使用它们。
大多数预定义变量中的值可以通过替代方法访问。
下表列出了所有Ruby的预定义变量。
没有 | 变量名称和描述 |
---|---|
1 | $!
提出的最后一个异常对象。也可以在rescue子句中使用=>来访问异常对象。 |
2 | $ @
堆栈回溯募集的最后一个异常。堆栈回溯信息可以通过Exception#backtrace方法检索最后一个异常。 |
3 | $ /
输入记录分隔符(默认为换行符)。获取,readline等,将他们的输入记录分隔符作为可选参数。 |
4 | $
输出记录分隔符(默认为nil)。 |
5 | $,
要打印的参数和Array#join之间的输出分隔符(默认为nil)。您可以将数组明确指定给Array#join。 |
6 | $;
split的默认分隔符(默认为nil)。您可以为String#split指定明确的分隔符。 |
7 | $。
从当前输入文件读取的最后一行的编号。相当于ARGF.lineno。 |
8 | $ <
ARGF的同义词 |
9 | $>
$ defout的同义词。 |
10 | $ 0
正在执行的当前Ruby程序的名称。 |
11 | $$
正在执行的当前Ruby程序的进程pid。 |
12 | $?
最后一个进程的退出状态终止。 |
13 | $:
$ LOAD_PATH的同义词。 |
14 | $ DEBUG
如果指定了-d或--debug命令行选项,则为true。 |
15 | $ defout
print和printf的目标输出(默认为$ stdout)。 |
16 | $ F
指定-a时接收分割输出的变量。如果指定-a命令行选项以及-p或-n选项,则设置此变量。 |
17 | $ FILENAME
目前正在从ARGF读取的文件的名称。相当于ARGF.filename。 |
18 | $ LOAD_PATH
一个数组,用于加载和要求方法加载文件时要保存要搜索的目录。 |
19 | $ SAFE
安全级别 0→不对外部提供(污染)数据执行检查。(默认) 1→禁止使用污染数据的潜在危险操作。 2→禁止对进程和文件进行潜在危险的操作。 3→所有新创建的对象都被认为是污染的。 4→禁止修改全局数据。 |
20 | $ stdin
标准输入(默认为STDIN)。 |
21 | $ stdout
标准输出(默认为STDOUT)。 |
22 | $ stderr
标准错误(默认为STDERR)。 |
23 | $ VERBOSE
如果指定了-v,-w或--verbose命令行选项,则为True。 |
24 | $ - x
解释器选项-x(x = 0,a,d,F,i,K,l,p,v)的值。这些选项列在下面 |
25 | $ -0
解释器选项-x的值和$ /的别名。 |
26 | $ -a
解释器选项-x的值,如果选项-a被设置,则为true。只读。 |
27 | $ -d
解释器选项-x的值和$ DEBUG的别名 |
28 | $ -F
解释器选项-x和别名$ ;. |
29 | $ -i
解释器选项-x和in-place-edit模式的值保存扩展名,否则为nil。可以启用或禁用就地编辑模式。 |
30 | $ -I
解释器选项-x的值和$:的别名。 |
31 | $ -l
解释器选项-x的值,如果选项-lis设置为true。只读。 |
32 | $ -p
解释器选项-x的值,如果选项-pis设置为true。只读。 |
33 | $ _
局部变量,最后一个字符string通过gets或readline在当前作用域中读取。 |
34 | $〜
与最后一场比赛相关的局部变量MatchData。Regex#match方法返回最后一个匹配信息。 |
35 | $ n($ 1,$ 2,$ 3 ...)
在最后一个模式匹配的第n组中匹配的字符string。相当于m [n],其中m是MatchData对象。 |
36 | $&
在最后一个模式匹配中匹配的字符string。相当于m [0],其中m是MatchData对象。 |
37 | $`
在最后一个模式匹配的匹配之前的字符string。相当于m.pre_match,其中m是MatchData对象。 |
38 | $"
匹配后的字符string在最后一个模式匹配。相当于m.post_match,其中m是MatchData对象。 |
39 | $ +
与最后一个模式匹配的最后一个成功匹配的组对应的字符string。 |
下表列出了所有Ruby的预定义常量 -
注 - TRUE,FALSE和NIL都向后兼容。最好使用true,false和nil。
没有 | 常数名称和描述 |
---|---|
1 | 真正
同义词为真。 |
2 | 假
同义词为虚假。 |
3 | 零
同义词为零。 |
4 | ARGF
如果没有命令行参数,则提供对作为命令行参数传递的文件的虚拟级联访问的对象或标准输入。$的同义词。 |
5 | ARGV
包含传递给程序的命令行参数的数组。$ *的同义词。 |
6 | 数据
用于读取__END__指令后面的代码行的输入流。如果__END__不在代码中,则不定义。 |
7 | ENV
包含程序的环境变量的类似哈希的对象。ENV可以作为哈希处理。 |
8 | RUBY_PLATFORM
一个指示Ruby解释器平台的字符string。 |
9 | RUBY_RELEASE_DATE
指示Ruby解释器发布日期的字符string |
10 | RUBY_VERSION
一个指示Ruby解释器版本的字符string。 |
11 | STDERR
标准错误输出流。$ stderr的默认值。 |
12 | STDIN
标准输入流。$ stdin的默认值。 |
13 | STDOUT
标准输出流。默认值$ stdout。 |
14 | TOPLEVEL_BINDING
在Ruby顶级的绑定对象。 |
标准的Ruby发行版包含有用的工具以及解释器和标准库 -
这些工具可帮助您调试和改进Ruby程序,而不用花费太多的精力。本教程将为您提供一个非常好的开始,这些工具。
RubyGems是一个用于Ruby的软件包实用程序,它可以安装Ruby软件包并保持最新。
为了帮助处理错误,Ruby的标准发行版包括一个调试器。这与gdb实用程序非常相似,可用于调试复杂程序。
irb(Interactive Ruby)由Keiju Ishitsuka开发。它允许您在提示符下输入命令,并让解释器像执行程序一样进行响应。irb可用于实验或探索Ruby。
通过查找瓶颈,Ruby profiler可以帮助您提高缓慢程序的性能。
还有其他有用的工具不会与Ruby标准分发捆绑在一起。但是,您需要自己安装。
eRuby stands for embedded Ruby. It"s a tool that embeds fragments of Ruby code in other files, such as HTML files similar to ASP, JSP and PHP.
ri: Ruby Interactive Reference −
When you have a question about the behavior of a certain method, you can invoke ri to read the brief explanation of the method.
For more information on Ruby tool and resources, have a look at Ruby Useful Resources.