Ruby操纵外部数据(四)

    技术2022-05-11  16

    3 、使用Marshal 完成有限制的" 深层拷贝"

    Ruby没有深层拷贝"deep copy"操作符。方法dupclone不会总像你想像的那样工作。 对象可以包含嵌套的对象引用,它转向一个拷贝操作到Pick Up Sticks中。

    我们提供了一个途径来处理一个有限制的深层拷贝( 它有限制,是因为它还以Marshal 为基础所以有同样内在限制) def deep_copy(obj) Marshal.load(Marshal.dump(obj)) end a = deep_copy(b) 4 Better Object Persistence with PStore PStore 库提供了文件为基础的Ruby 对象的永续存储。PStore 对象可以持有许多Ruby 对象层次。每个层次通过一个键有个被识别的根。开始时从磁盘文件上读取层次结束时写回文件。这儿是个例子: require "pstore" # save db = PStore.new("employee.dat") db.transaction do db["params"] = { "name" => "Fred", "age" => 32, "salary" => 48000 } end # retrieve require "pstore" db = PStore.new("employee.dat") emp = nil db.transaction { emp = db["params"] } 典型地,我们将Pstore 对象传入到处理块内。但是,我们也可以直接使用调用者。 这个技术是事务导向的;块开始时,数据被从磁盘文件中取回并进行处理。然后,它被显式地写回到磁盘上。

    在事务的中间,我们即可以中断也可放弃;但前者将保留我们做的修改,而后者将丢掉它们。参考Listing4.2这个更长的例子。

    Listing 4.2 Using PStore require "pstore" store = PStore.new("objects") store.transaction do |s| a = s["my_array"] h = s["my_hash"] # Imaginary code omitted, manipulating # a, h, etc. # Assume a variable named "condition" having # the value 1, 2, or 3... case condition when 1 puts "Oops... aborting." s.abort # Changes will be lost. when 2 puts "Committing and jumping out." s.commit # Changes will be saved. when 3 # Do nothing... end puts "We finished the transaction to the end." # Changes will be saved. end 在一个事务内部,你也可以使用方法roots 来返回根的数组( root? 测试成员) 。同样,delete 方法将有效地移除一个根。这儿个例子: store.transaction do |s| list = s.roots # ["my_array","my_hash"] if s.root?("my_tree") puts "Found my_tree." else puts "Didn't find # my_tree." end s.delete("my_hash") list2 = s.roots # ["my_array"] end 5 Using the dbm Library dbm 库是一个简单依赖系统的,以字符为基础的哈希表的,以文件存储的机制。它存储键和关联的数据,两者必须是字符串。Ruby dbm 接口是被标准按装的。 要使用这个类,创建一个与文件名字关联的dbm 对象,并且你希望以字符为基础的哈希表工作。当你完成时,你应该关闭文件。这儿是个例子: require 'dbm' d = DBM.new("data") d["123"] = "toodle-oo!" puts d["123"] # "toodle-oo!" d.close puts d["123"] # RuntimeError: closed DBM file e = DBM.open("data") e["123"] # "toodle-oo!" w=e.to_hash # { "123"=>"toodle-oo!"} e.close e["123"] # RuntimeError: closed DBM file w["123"] # "toodle-oo! 这儿,dbm 被做为混插了Enumerable 的单独类实现的。两个类方法,new open ,是单态的,它的意思是任何时候,你的每个数据文件只可以有一个dbm 对象: q=DBM.new("data.dbm") # f=DBM.open("data.dbm") # Errno::EWOULDBLOCK: # Try again - "data.dbm" 它有34 个实例方法,很多都是别名或与Hash 方法类似。基本上,如果你能熟练地使用哈希表,你可以对一个dbm 对象应用同样的操作。 方法to_hash 将在内存中为哈希表文件制做一个拷贝,close 方法将永久地关闭与哈希表文件的连接。其余的方法和Hash 方法类似,但没有rehsh,sort,default, efault= 方法。to_s 方法只返回用字符串表示的对象ID 三、连接外部数据库 Ruby 可以连接由许多不同的人开发的,各种各样的数据库。这些范围从整体系统譬如Oracle 到对更小的MySQL

    这些包的功能层会持续地被修改。请务必提到网上参考最新的信息。Ruby的应用文档(RAA)总是最好的起点。

    1 、连接到MySQL Ruby MySQL 接口是最稳定的和有完整功能的数据库接口。它是扩展的,必须在Ruby MySQL 被安装并运行后才可安装。如果你升级Ruby ,你将需要重新安装它。它的安装很简单,使用Ruby make 过程。 一旦你安装了它,可以有三个步骤来使用它。首先,在你的脚本中加载它;然后连接到数据库。最后,用你的表工作。连接请求通常使用的参数主机名,用户名,口令,数据库,等等,像这儿显示的: require 'mysql' m = Mysql.new("localhost","ruby","secret","maillist") r = m.query("SELECT * FROM people ORDER BY name") r.each_hash do |f| print "#{ f['name']} - #{ f['email']} " end 这儿是部分输出: John Doe - jdoe@rubynewbie.com Fred Smith - smithf@rubyexpert.com Don Jackson - don@perl2.com Jenny Williams - jwill27@miss-code.com 类方法Mysql.new MysqlRes.each_hash 是非常有用的,还有随同的实例方法query 这个模块由四个类组成: Mysql, MysqlRes, MysqlField, MysqlError, 分别在README 文件中描述。我们在这儿总结了一些有用的方法,但你可以实际文档中找到更多信息。 类方法Mysql.new 接受几个字符串参数,所有都被定义为nil ,并且它返回一个connection 对象。参数是host,user,passwd,db,port,sock, flag new 的别名real_connect connect 方法create_db, select_db, drop_db 都接受数据库名称做为参数;它们用法显示在下面( 方法close 将关闭与服务端的连接) m=Mysql.new("localhost","ruby","secret") m.create_db("rtest") # Create a new database m.select_db("rtest2") # Select a different database m.drop_db("rtest") # Delete a database m.close # Close the connection The method 方法list_dbs 将返回有效的数据库名称列表在一个数组内: dbs = m2.list_dbs # ["people","places","things"] query 接受一个字符串参数并缺省地返回一个MysqlRes 对象。这依赖于query_with_result 是如何被设置的,它可以返回一个Mysql 对象。 如果事件出现错误,错误号码可由errno 取回;换句话说,error 将返回实际的错误信息。这儿是个例子: begin r=m.query("create table rtable ( id int not null auto_increment, name varchar(35) not null, desc varchar(128) not null, unique id(id) )") # exception happens... rescue puts m.error # Prints: You have an error in your SQL syntax # near 'desc varchar(128) not null , # unique id(id) # )' at line 5" puts m.errno # Prints 1064 # ('desc' is reserved for descending order) end MysqlRes 内很少被使用的方法被总结列在下面: 1. fetch_fields 从下一行中返回MysqlField 对象的数组。 2. fetch_row 从下一行中返回字段值的数组。 3. fetch_hash(with_table=false) 返回包含下一行的名称和值的哈希表。 4. num_rows 返回结果集中行数。 5. each 按次序返回字段值数组的迭代器。 6. each_hash(with_table=false) 按次序返回一个{fieldname => fieldvalue} 样哈希表的迭代器。( 使用x['field name'] 来获取字段值。) 这儿是MysqlField 的一些实例方法: 1. name 返回指定字段的名字。 2. table 返回指定字段所属表的名字。 3. length 返回字段定义长度。 4. max_length 从结果集中返回长度最长的字段。 5. hash Returns a hash with a name and values for name, table, def, type, length, max_length, flags, and decimals 这儿的材料总是代替不了在线文档的。更多信息可参考MySQL Web 站点 ( www.mysql.com) Ruby 应用文档。  

    最新回复(0)