-2

我有一个客户端模型,在下面的实例变量中我收集了所有标识符。

@all_clients = Client.all.collect{|a| a.identifier}

这返回["client123", "client234", "client567", "client789"]

此外,我有一个变量@create_id =“client123”,我正在检查集合中是否存在@create_id 的值,方法是@all_clients.include? @create_id 如果返回true,我将像这样将“_1”附加到它:@create_id<<"_1"并保存@create_id稍后创建客户端通过那个ID。

我再次检查@create_id集合中是否存在最新的“client123_1”,如果是,我添加_2并进一步检查并最终保存。这是我所知道的最糟糕的检查任何东西的方法,因为我是编程新手。

有人可以帮我找到一种有效的方法来做到这一点。

我需要做的就是首先检查集合是否存在我的变量,如果不存在,然后将 _1 附加到它,然后检查 string_1 是否已经存在并进一步移动到 _2 或 _3 以及更远。下划线和整数根据检查集合保持递增。

提前致谢

4

1 回答 1

2

您可以将 AR 查询限制为仅包含与您的前缀匹配的记录@create_id

clients=Client.arel_table
matching_clients = Client.where( clients[:identifier].matches( "#{@create_id}%" ) )

如果matching_clients为空,则还没有具有该标识符前缀的客户端。否则,现在您可以提取整数后缀片段并找出下一个可用的 id 是什么。

last_suffix = matching_clients.
  map(&:identifier).
  map { |s| (s.split('_',2)[1] || 0).to_i }.
  max

如果标识符字段由索引支持,这应该是相当有效的。

如果您的方案使用的后缀格式允许对后缀进行正确的词法排序(例如,始终将后缀填充到固定宽度),那么您可以通过仅要求最大的索引将更多的工作推入带有索引的数据库中匹配的标识符。

请注意,如果您有多个并发进程可能想要创建新的唯一标识符,则整个方法会受到竞争条件的影响。如果您的数据库模式具有唯一索引clients.identifier(也支持查询效率),那么当您尝试使用您制造的新标识符保存记录时,数据库将引发唯一性约束错误,在这种情况下您可以继续尝试重新选择并派生新的候选标识符,直到您再次成功。

于 2013-02-14T07:34:41.653 回答