Ruby on rails RubyonRails-将活动记录结果与包含新实例对象的数组进行比较

Ruby on rails RubyonRails-将活动记录结果与包含新实例对象的数组进行比较,ruby-on-rails,ruby,json,activerecord,ruby-on-rails-2,Ruby On Rails,Ruby,Json,Activerecord,Ruby On Rails 2,在我的Rails应用程序中,我做了两件事——将活动记录结果与从外部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

在我的Rails应用程序中,我做了两件事——将活动记录结果与从外部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
<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>
这是一个新版本,因为在过去几周中,每种方法的结果集急剧增加之后,旧版本花费的时间太长

 # 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
我发现这很困难,因为它是以前用来显示这些孤立数字(两次迭代)的相同视图和部分视图,但它是遗留代码,所以我从未见过它在实际工作中,但我只是对它以前如何与活动记录结果和正常数组一起工作感到困惑

这一观点只是:

<%= render :partial => 'list_item', :collection => @telco_numbers ) %>

因此,据我所知,对于我试图修复的版本,它将有一个
addnew
链接,而不是一个
Edit
操作,因为它还不在我的数据库表中,所以我只是想弄清楚如何重构效率低下的版本,以便它仍能与共享视图一起工作

如果有帮助,JSON API响应的格式为:

[{"country_code":"44","number":"1133508889","block":null,"type":"Legacy","SMS":"0"},
因此,只有
country\u 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
my view html表中的数字列只包含
+
字符,而
添加新的
链接对于
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

但是首先你要减少你的数据库呼叫

 self.find(:all) #stupid slow
我会告诉你正确的方向

self.where('number NOT IN (?)', array_of_phone_numbers)

这将找到所有不在json数据中的记录。

但首先您需要减少db调用

 self.find(:all) #stupid slow
我会告诉你正确的方向

self.where('number NOT IN (?)', array_of_phone_numbers)

这将找到所有不在json数据中的记录。

如果在电信公司中找到
孤立的\u编号后,在该集合中为每个编号创建一个模型实例,然后将其推送到一个表中以返回这些编号,该怎么办。。。或者至少是那个方向的东西。e、 g

orphaned_results = []
orphaned_numbers.each do |n|
 item = self.new()
 item.id = n
 orphaned_results.push(item)
end

return orphaned_results
然后,在调用
addnew
时,您只需在该实例上调用
save
,即可从partial部分调用

这样,您就不会有分部的活动记录和数组问题,因为您将返回一个活动记录实例数组

另外,我对加快速度的建议是使用散列来存储键/数字

希望有帮助

更新

为了获得countrycode并加快速度,我将继续我的哈希建议:

因此,让我们从您的初始实现开始:

#this returns everything from the API
all_numbers = self.all_telco

#this returns a Hash in the form {:number => :country_code}
listed_numbers = Hash[all_numbers.map{|x| [x.number,x.country_code]}] 
#so now you can do
orphaned_numbers = listed_numbers.keys - db_numbers
orphaned_results = []
orphaned_numbers.each do |n|
  item = self.new()
  item.number = n
  item.countrycode = listed_numbers[n]
  orphaned_results.push(item)
end

return orphaned_results

这将给它一个提升,并将国家代码发送到前端

对于电信公司中的
孤立\u
方法,如果在找到
孤立\u号码后,为该集合中的每个号码创建一个模型实例,然后将其推送到表中以返回这些号码,该怎么办。。。或者至少是那个方向的东西。e、 g

orphaned_results = []
orphaned_numbers.each do |n|
 item = self.new()
 item.id = n
 orphaned_results.push(item)
end

return orphaned_results
然后,在调用
addnew
时,您只需在该实例上调用
save
,即可从partial部分调用

这样,您就不会有分部的活动记录和数组问题,因为您将返回一个活动记录实例数组

另外,我对加快速度的建议是使用散列来存储键/数字

希望有帮助

更新

为了获得countrycode并加快速度,我将继续我的哈希建议:

因此,让我们从您的初始实现开始:

#this returns everything from the API
all_numbers = self.all_telco

#this returns a Hash in the form {:number => :country_code}
listed_numbers = Hash[all_numbers.map{|x| [x.number,x.country_code]}] 
#so now you can do
orphaned_numbers = listed_numbers.keys - db_numbers
orphaned_results = []
orphaned_numbers.each do |n|
  item = self.new()
  item.number = n
  item.countrycode = listed_numbers[n]
  orphaned_results.push(item)
end

return orphaned_results

这将给它一个提升,并将国家代码发送到前端

有趣,数字列是否已索引?@TheIrishGuy,刚刚选中,
number
和其他5列已索引(包括主键)有趣,数字列是否已索引?@TheIrishGuy,刚刚选中,
number
和其他5列已索引(包括主键)谢谢,但在数据库中查找api中不存在的数字是可行的(但我会采纳这一建议并努力改进它),相反,我正在努力获取api中存在但数据库中不存在的数字。谢谢,但在数据库中查找api中不存在的数字是可行的(但我会接受这个建议并努力改进它),我正在努力解决的恰恰相反——获取API中但不在数据库中的数字。谢谢,现在运行,渲染后仍然非常慢(DB约为60000,API约为150000)(仍然需要很长时间才能完成),my view html表中的数字列只包含
+
字符,
添加新的
链接没有
countrycode
number
url参数的任何值,有什么想法吗?我更新了我的答案,基本上你没有看到我第一个答案中的数字和countrycode,因为我使用了
id
而不是
number
,我没有在返回的模型实例中添加
countrycode
。希望现在能有更多帮助。享受吧!谢谢,我刚刚会尝试一下。它似乎运行了,但当它完成时,会出现500个错误-即使是在开发阶段。日志上只显示:
状态:500内部