我发现写Rails,尤其是测试部分,需要reload的次数相当频繁。比方说

user = users(:xxxxx)
xhr :put, 'change_xxxxx', :id => user.id
user.reload # necessary!
assert user.xxx, xxx
assert user.yyy, yyy

由于这里创建的user对象和被测试的action里的user对象(在内存概念上)不是同一个对象,因此,被测试的action修改了user对象在数据库里的数据,会导致外围的user信息过时,因此必须reload,否则接下来的断言语句都无法通过。

这种情况同样也有可能存在与关联对象上,比如

assert child1.father, child2.father
child1.father.name = 'new name'
child1.save
child2.reload # necessary!
assert child2.father.name, 'new name'

总是写很多reload语句显然很不舒服,为此我今天在回家的地铁上想了一种解决方案,就是在后台全局的部分,以ActiveRecord类名和实例为key简单的缓存一部分数据,这部分数据与数据库里的数据在本次request返回内一致,request结束后自动清除以免内存泄露和影响下一个request。而前面的ActiveRecord对象,本身仅存储那些还未被保存的数据。

方案大致是这样的(以Rails 2.3为例):

require 'active_record'

module ActiveRecord
  class Base
    def request_cache
      self.class.request_cache[self]
    end

    def request_cache=(v)
      self.class.request_cache[self] = v
    end
  end

  class << Base
    def request_cache
      @request_cache ||= Hash.new {|h, k| h[k] = Hash.new {|h, k| h[k] = {}}}
      @request_cache[name]
    end
  end
end

ActionController::Dispatcher.middleware.use(Class.new do
  def initializer(app)
    @app = app
  end

  def call(env)
    @app.call(env)
  ensure
    ActiveRecord::Base.request_cache.clear
  end
end)

这里我把缓存就设计在ActiveRecord的class variable内(三级Hash,分别是类-实例对象-属性名),然后用Middleware的方式去清理缓存,之所以选择用Middleware的方式是因为ActiveRecord原本和HTTP Request是不能发生关联的,否则Console和Unit test里就无法执行了,设计成Middleware则能很好的解决这一问题。

由于选择的三级Hash的设计中没有直接和数据库关联的信息,因此其实也可以用于非ActiveRecord类(唯一要做的可能仅仅是自己实现一种标示方法),毕竟当前可以用于存储的服务早已不止数据库一种了。

至于对于ActiveRecord的修改我现在对ActiveRecord的实现还不够熟悉,无法完成,以后学习这一部分了再说吧。但是大致的思路是这样的:

  • 当从数据库读入数据的时候(包括reload),将缓存里的数据翻新
  • 当保存数据进数据库的时候,将数据同样保存进缓存
  • 当从一个ActiveRecord对象读取属性的时候,现在被当前对象修改过的属性中搜索,如果搜索不到再从缓存里搜索,如果还是搜索不到就采用默认方法

大致就是这些了,其实想法还是很简单的,希望早日自己能把它变成现实。

114域名纠错大家应该都见过,也都该知道这是什么东西。这个东西真的神出鬼没,有时候现在114,过几分钟就不114了,有时候一个浏览器114,换个浏览器又不114了,还视家庭状况而定,在我家,114似乎格外变态,我已经开启了SSH,照样114,让我苦恼了好久。不过最近终于找到了个办法来对付它。

(这张图是网上搜的)

Google Chrome有一个负责通信的后台,地址是 chrome://net-internals/ ,通过它可以查看Chrome的一些与网络相关的信息。进入DNS标签页面,也可以用 chrome://net-internals/#dns 来进入

点击“Clear host cache”按钮,清除之。然后去访问一个会触发114域名纠错的地址,比如我今天访问的 http://www.ikde.org/,然后进入114地址纠错界面。返回 chrome://net-internals/#dns,可以看见大量DNS解析后的IP地址被刷出。(由于被解析出的IP地址很多,其中甚至还有Google的地址)请仔细挑选其中那些与114相关的IP地址,可以记录下来。由于那些地址可能非常杂乱并有一些重复,你可以使用

sort -n | uniq

命令去重复。然后前往自己使用的路由器的地址,比如 192.168.1.1,你可能需要密码才能进入。进入路由器的设定页面后,找到防火墙,这里各家用的路由器不一样,操作也都不一样。

点击添加,进入添加页面

通讯协议选择“TCP”,来源地址选择“SINGLE”,输入要屏蔽的IP地址,启用即可。各家的路由器操作可能都不相同,我这个路由器不是很好,操作很不人性化,地址要一个一个添加,不能批量添加,速度也很慢。

全部完成后,退出即可。此时再尝试那个会触发114域名纠错的地址,应该就可以直接打开了,如果不行,刷新几次试试。如果再不行,大概就是真的被屏蔽了。