我想在我正在构建的应用程序中使用UUID,但遇到了一点问题。由于UUID(v4)是随机生成的,所以无法排序,我试图首先覆盖ActiveRecord::Base#,但Rails对此不太满意。它对我大喊ArgumentError: You tried to define a scope named "first" on the model "Item", but Active Record already defined a class method with the same name.
如果我想排序并让它正确排序,我必须使用不同的方法吗?
这是酱料:
# lib/sortable_uuid.rb
module SortableUUID
def self.included(base)
base.class_eval do
scope :first, -> { order("created_at").first }
scope :last, -> { order("created_at DESC").first }
end
end
end
# app/models/item.rb
class Item < ActiveRecord::Base
include SortableUUID
end
Rails 4.2、Ruby 2.2.2
参考文件:
4条答案
按热度按时间camsedfj1#
Rails 6(当前版本为6.0.0rc1)提供了implicit_order_column!
按
created_at
排序,生成.first
、.last
、.second
等。尊重就像这样简单:zour9fqk2#
首先,
first
和last
并不像你想象的那么简单:你完全忽略了这两个方法都支持的limit
参数。其次,
scope
只不过是添加用于返回查询的类方法的一种奇特方式。您的作用域滥用了scope
,因为它们返回单个模型示例而不是查询。你根本不想使用scope
,你只是想替换first
和last
类方法,那么为什么不直接覆盖它们呢?但是,您需要正确地覆盖它们,这将需要阅读和理解Rails源代码,以便正确地模仿find_nth_with_limit
的功能。你会想要覆盖second
,third
,.还有其他那些愚蠢的方法如果你觉得不应该替换
first
和last
(这在IMO是件好事),那么你可以添加一个默认作用域来按需排序:当然,默认作用域也有其自身的问题,像这样偷偷地把东西放入ORDER BY中可能会迫使您在任何时候真正想要指定ORDER BY时调用
reorder
;记住,多次调用order
会添加新的排序条件,它们不会替换已经存在的条件。或者,如果您使用的是Rails 6+,您可以使用Markus's
implicit_order_column
solution来避免默认作用域可能导致的所有问题。我觉得你完全搞错了。每当我看到
M.first
时,我都认为有些东西被遗忘了。通过id
排序几乎是无用的,所以你应该在使用first
和last
这样的方法之前,总是手动指定你想要的顺序。z5btuh9x3#
在将
id
替换为uuid
之后,我在关联分配外键的方式上遇到了一些奇怪的情况,并不是.last
和.first
,而是因为我忘记了使用uuid将default: 'gen_random_uuid()'
添加到其中一个表中。一旦我修好了,问题就解决了。jjhzyzn04#
根据这里链接的rails文档,最好的方法是确保为您想要使用的UUID添加默认选项。关于选择UUID链接here的好文章。我使用了ULID,因为它们是可排序的,并且将我的UUID选项指定为ULID,我的记录是可排序的!