惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 【当耐特】
Help Net Security
Help Net Security
P
Proofpoint News Feed
J
Java Code Geeks
爱范儿
爱范儿
Last Week in AI
Last Week in AI
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
F
Full Disclosure
Google DeepMind News
Google DeepMind News
H
Help Net Security
G
Google Developers Blog
Jina AI
Jina AI
Vercel News
Vercel News
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
L
Lohrmann on Cybersecurity
S
Schneier on Security
Microsoft Azure Blog
Microsoft Azure Blog
IT之家
IT之家
Security Archives - TechRepublic
Security Archives - TechRepublic
阮一峰的网络日志
阮一峰的网络日志
N
News and Events Feed by Topic
GbyAI
GbyAI
B
Blog
O
OpenAI News
博客园_首页
Cisco Talos Blog
Cisco Talos Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Hacker News: Ask HN
Hacker News: Ask HN
TaoSecurity Blog
TaoSecurity Blog
腾讯CDC
MongoDB | Blog
MongoDB | Blog
M
MIT News - Artificial intelligence
C
Cybersecurity and Infrastructure Security Agency CISA
Cyberwarzone
Cyberwarzone
Webroot Blog
Webroot Blog
Simon Willison's Weblog
Simon Willison's Weblog
Y
Y Combinator Blog
C
Cisco Blogs
A
Arctic Wolf
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
T
The Exploit Database - CXSecurity.com
Security Latest
Security Latest
AI
AI
W
WeLiveSecurity
aimingoo的专栏
aimingoo的专栏
The Register - Security
The Register - Security
Project Zero
Project Zero
H
Hackread – Cybersecurity News, Data Breaches, AI and More
N
Netflix TechBlog - Medium
Blog — PlanetScale
Blog — PlanetScale

博客园 - Tachikoma

用Ruby实现 Web Service Server ,并用Ruby发送 HTTP请求 Web Service Android 使用 Ksoap2 出现的低级错误... - Tachikoma Cygwin中通过RJB在Ruby下调用ICTCLAS(JAVA) ICTCLAS4J 的编译脚本 Ruby Sandbox 实现运行客户代码 - Tachikoma ruby 下使用 ICTCLAS(JAVA) RJB 在windows下的一些安装事项 Ruby手工测试正确,rcov测试失败的解决 在dell dimension 5150 上安装 leopard 手记 Rails测试中清空数据表/载入空fixtures RDoc 解决同名module 与 Class的问题 C 实用的 e-editor 的bundle Best of Ruby Quiz - Animal Quiz Best of Ruby Quiz - GEDCOM Parser Best of Ruby Quiz - MadLib - Tachikoma 使用selenium-on-rails的一些讨论 3]assertXpathCount的使用 使用selenium-on-rails的一些讨论 2]清理缓存 - Tachikoma - 博客园 使用selenium-on-rails的一些讨论 [0,1] 关于 rails ActiveRecord 属性 以及 foreign_key 不直接用数据库项目 时的一些讨论
Ruby在使用MongoDB时,对Cursor的重新包装
Tachikoma · 2010-03-15 · via 博客园 - Tachikoma

MongoDB是个好东西,作为非关系数据库,十分的便利,符合Ruby的一贯精神

在使用中,出现了以下问题:
  调用 DB.collection.find(...) 返回的对象是 Cursor,而Cursor#each 或 Cursor#next_document ... 的对象是OrderedHash
  我们难免会设计数据库层来简化数据库通讯,我们设定以下语境来描述这个问题:

class Sample
	...
	def self.find(hash = nil)
		cursor = self.collection.find(hash)
		cursor
	end
	
	def self.to_sample(ordered_hash)
		...
	end
	...
end

 Sample 对应于一个Collection,Sample#find返回一个cursor,而我们使用的方法大致如下:

Sample.find.each |hash|
	sample = Sample.to_sample(hash)
	...
end

这是段极其Ugly的代码,每次我们从Sample#find获得的对象都要 to_sample一下才能使用,不得不考虑Ruby强大解决能力:

class Sample
	...
	def initialize(ordered_hash)
		...
	end
	#instead of :
	#def self.to_sample(ordered_hash)
	#	...
	#end
	
	def self.find(hash = nil)
		cursor = self.collection.find(hash)
		class << cursor
			alias :old_next_document :next_document
			def next_document
				hash = old_next_document
				Sample.new(hash)
			end
		end
		cursor
	end	
	...
end

对于cursor实例,采用了Ruby 的 singleton class (区别于设计模式中的单例模式),动态包装了next_document方法(next_document 是 each 等其他方法的基础,是Cursor中唯一获取记录的函数),Sample.find.next_document 返回 Sample对象,一切顺利,这样看似解决了问题

但是当我们有了多个Collection类,并需要提取出一个基类时问题就来了:
  假设我们的基类叫Coll,代码如下:

class Coll
	...
	def initialize(ordered_hash)
		...
	end
	#instead of :
	#def self.to_sample(ordered_hash)
	#	...
	#end
	
	def self.find(hash = nil)
		cursor = self.collection.find(hash)
		class << cursor
			alias :old_next_document :next_document
			def next_document
				hash = old_next_document
				Coll.new(hash)
			end
		end
		cursor
	end	
	...
end

我们只是将Sample换成了Coll,而next_document中的Coll.new(hash)很显然不符合我们的要求(不能初始化成适当的子类,只能生成Coll类实例) 。比如此时我们调用Sample.find.next_document,获得的就只能是Coll类的实例(当然也很有可能出错)。问题集中在 Singleton class 的代码没有根据调用类(Sample)动态生成,当使用Ruby的时候,很显然这不可饶恕:

class Coll
	...
	def initialize(ordered_hash)
		...
	end
	#instead of :
	#def self.to_sample(ordered_hash)
	#	...
	#end
	
	def self.find(hash = nil)
		cursor = self.collection.find(hash)
		cursor.instance_eval <<-EOT
			alias :old_next_document :next_document
			def next_document
				hash = old_next_document
				#{self}.new(hash)
			end
		EOT
		cursor
	end	
	...
end
class Sample < Coll
end

It's better , ha. 我们动态生成了字符串作为执行代码,为单独的cursor实例生成了单独的next_document方法,返回特定的对象(Sample.find.each 返回 Sample对象,Blurblur.find.each 返回Blurblur对象)