【发布时间】:2013-11-18 12:46:54
【问题描述】:
在我的 Rails 应用程序中,我正在做两件事 - 将 Active Record 结果与从外部 API 的 JSON 响应构建的数组进行比较。
第一步是检查哪些结果在数据库中而不是在 API 中,我这样做如下:
def self.orphaned_in_db
db_numbers = self.find(:all).map{|x| x.number}
listed_numbers = self.all_telco.map{|x| x.number} # gets JSON from API
orphaned_numbers = db_numbers - listed_numbers
orphaned_results = self.find_all_by_number(orphaned_numbers)
return orphaned_results
end
这是新版本,因为在过去几周每个结果集急剧增加后,旧版本花费了太长时间。
# def self.orphaned_in_db
# old version
# db_numbers = self.find(:all)
# listed_numbers = self.all_telco
# orphaned_numbers = []
# db_numbers.each do |db|
# scan = listed_numbers.select{ |l| l.number == db.number}
# orphaned_numbers.push(db) if scan.empty?
# end
# return orphaned_numbers
# end
我现在发现做相反的事情很棘手 - 在 API 数组中查找不在我的数据库表中的数字。
def self.orphaned_in_telco
db_numbers = self.find(:all).map{|x| x.number}
all_numbers = self.all_telco
listed_numbers = all_numbers.map{|x| x.number}
orphaned_numbers = listed_numbers - db_numbers
orphaned_results = # how to filter all_numbers by orphaned_numbers?
return oprhaned_results
end
再一次,现在因为太慢而无法使用的旧方法:
# def self.orphaned_in_telco
# original, inefficient way
# db_numbers = self.find(:all)
# listed_numbers = self.all_telco
# orphaned_numbers = []
# listed_numbers.each do |l|
# scan = db_numbers.select{ |db| l.number == db.number}
# orphaned_numbers.push(l) if scan.empty?
# end
# return orphaned_numbers
# end
我发现这很困难,因为它与之前用于显示这些孤立数字(两次迭代)的视图和部分视图相同,但它是遗留代码,所以我从未见过它在实际工作中,但我只是很困惑它是如何工作的以前使用 Active Record 结果和普通数组。
视图只是:
<%= render :partial => 'list_item', :collection => @telco_numbers ) %>
其中@telco_numbers设置为上述方法的返回值。 (@telco_numbers = TelcoNumber.orphaned_in_telco params[:page])
部分如下:
<tr>
<td>
<%= (link_to list_item.organisation.name.truncate(30), :controller => 'organisation', :action => 'update', :id => list_item.organisation.id) if list_item.organisation %>
</td>
<td class="centre"> <%= link_to ((list_item.countrycode == "44" ? Telco.format_uk_number(list_item.number) : "+#{list_item.countrycode} #{list_item.number}")), {:action => 'update', :id => list_item.id} %></td>
<td class="centre"><%= list_item.route_technology %></td>
<td><%= list_item.route_destination if list_item.route_destination %></td>
<td class="centre">
<% if !list_item.new_record? %>
[ <%= link_to 'Edit', {:action => 'update', :id => list_item.id} %> ]
<% else %>
[ <%= link_to 'Add New', {:action => 'update', :telco_number => list_item.attributes } %> ]
<% end %>
</td>
据我了解,对于我要修复的版本,它不会有一个 Edit 操作,而是有一个 Add New 链接,因为它不在我的数据库表中,所以我只是想弄清楚如何重构低效版本,以便它仍然可以与共享视图一起使用。
如果有帮助,JSON API 响应的格式是:
[{"country_code":"44","number":"1133508889","block":null,"type":"Legacy","SMS":"0"},
所以只有country_code 和number 对应于我的数据库表中的列,其余的不是必需的,因此部分中的if 语句只显示某些可用的参数。
更新
按照 Chris Vo 的建议将方法更改为以下方法后,经过很长时间才能完成,它终于可以工作了,但仍然不太正确。
def self.orphaned_in_telco
# original, inefficient way
db_numbers = self.find(:all)
listed_numbers = self.all_telco
orphaned_numbers = listed_numbers - db_numbers
orphaned_results = []
orphaned_numbers.each do |n|
item = self.new()
item.id = n
orphaned_results.push(item)
end
return orphaned_results
end
我的视图 html 表中的数字列仅包含 + 字符,Add New 链接对于 countrycode 和 number url 参数没有任何值(链接 url 是正确的,所有参数都是在查询字符串中,但它们都是空的)。
我的模型中的一些方法:
def self.max_search_results
return @@max_search_results
end
#for pagination
def self.per_page
20
end
def self.some_telco(per_page, page = 1)
page = 1 if page.nil?
api_call = TelcoApiv3.new("post", "/numbers/#{TelcoApiv3.account_id}/allocated/all")
listed_numbers = TelcoApiv3.poll(api_call.response["link"])
return listed_numbers.collect do |ln|
ln.store("countrycode", ln["country_code"])
TelcoNumber.new ln
end
end
def self.all_telco(page = 1)
listed_numbers = some_telco(@@max_nlist_results, page)
if listed_numbers.length == @@max_nlist_results
return listed_numbers.concat(all_telco(page + 1))
else
return listed_numbers
end
end
【问题讨论】:
-
有意思,数字列有索引吗?
-
@TheIrishGuy,刚刚检查,
number和其他 5 列已编入索引(包括主键)
标签: ruby-on-rails ruby json activerecord ruby-on-rails-2