我想用从外部API接收的值初始化检索到的对象中的一些属性。 after_find
和after_initialize
回调对我不起作用,因为我必须为每个接收的对象调用API,这是非常慢的。我想要以下内容:
class Server < ActiveRecord::Base
attr_accessor :dns_names
...
after_find_collection do |servers|
all_dns_names = ForeignLibrary.get_all_dns_entries
servers.each do |s|
s.dns_names = all_dns_names.select{|r| r.ip == s.ip}.map{|r| r.fqdn}
end
end
end
请注意,缓存不是解决方案,因为我需要始终拥有当前数据,并且数据可能会在应用程序之外进行更改。
答案 0 :(得分:1)
您需要一个类方法来增强数据中找到的每个服务器。所以,比如:
def index
servers = Server.where(condition: params[:condition]).where(second: params[:second])
@servers = Server.with_domains_names(servers)
end
class Server
def self.with_domain_names(servers)
all_dns_names = ForeignLibrary.get_all_dns_entries
servers.each do |s|
s.dns_names = all_dns_names.select{|r| r.ip == s.ip}.map{|r| r.fqdn}
end
end
end
这样,ForeignLibrary.get_all_dns_entries
只运行一次,您可以使用该额外信息增强服务器。
如果您希望每次初始化服务器对象时都这样做,我只需委托而不是使用after_initialize
。因此,您可以将所有dns条目有效地存储在全局变量中,然后将其缓存一段时间。 ForeignLibrary.get_all_dns_entries调用。所以,它会是这样的:
class Server
def dns_names
ForeignLibrary.dns_for_server(self)
end
end
class ForeignLibrary
def self.reset
@@all_dns_names = nil
end
def self.dns_for_server(server)
all_dns_names.select{|r| r.ip == server.ip}.map{|r| r.fqdn}
end
def self.all_dns_names
Mutex.new.synchronize do
@@all_dns_names ||= call_the_library_expensively
end
end
end
(我在这里也使用了一个互斥锁,因为我们正在使用|| = with class variables)
要使用它,你会:
class ApplicationController
before_filter do
ForeignLibrary.reset #ensure every page load has the absolute latest data
end
end