对于我的一个视图我想要包含一个带有jqueries typeahead函数的搜索字段。
数组应包含客户端的所有属性值。
查询数组按以下方式生成:
@clients = []
Client.each do |client|
@clients << client.attributes.values.join(' ')
end
这种方法对于大约3000个条目的数据集是否足够高效? 还是有更好更快的解决方案?
提前致谢。 干杯, 帕特里克
一位用户提到要实现它:
@clients = Client.map do |client|
client.attributes.values.join(' ')
end
这是另一种方法。但基准测试显示,这并没有改善业绩。
这给我留下了一个问题:也许有更高效的方式,但谈到最多3000条记录 - 这真的很重要吗?
答案 0 :(得分:5)
您可以使用.map
:
@clients = Client.map do |client|
client.attributes.values.join(' ')
end
答案 1 :(得分:4)
即使ActiveRecord模型实现了map
方法(他们认为我们不相信),OP和@xdazz建议的两个解决方案在时间和内存复杂性方面是等价的。这可以通过这个简单的基准来观察:
require 'fruity'
# Dummy client class
class Client < Struct.new(:first_name, :last_name, :position, :company)
class << self
include Enumerable
def each(&block)
5000.times do
yield Client.new('Firstname', 'Lastname', 'CEO', 'Company Inc.')
end
end
end
alias_method :attributes, :to_h
end
compare do
schnika do
clients = []
Client.each do |client|
clients << client.attributes.values.join(' ')
end
nil
end
xdazz do
clients = Client.map do |client|
client.attributes.values.join(' ')
end
nil
end
end
将输出
schnika is similar to xdazz
此外,当您查看map
(与collect
同义)的实现时,很明显除了OP的方法之外没有其他任何事情发生:
static VALUE
rb_ary_collect(VALUE ary)
{
long i;
VALUE collect;
RETURN_ENUMERATOR(ary, 0, 0);
collect = rb_ary_new2(RARRAY_LEN(ary));
for (i = 0; i < RARRAY_LEN(ary); i++) {
rb_ary_push(collect, rb_yield(RARRAY_PTR(ary)[i]));
}
return collect;
}
这转换为:
class Array
def collect
collect = []
self.each do |el|
collect << yield(el)
end
collect
end
end
答案 2 :(得分:1)
您可能不需要检索所有属性(例如'updated_at'),因此以下内容可能会更快:
@clients = Client.select([:name, :email, :id]).map do |client|
client.attributes.values.join(' ')
end
添加了id
,以防您需要链接到客户端。