我想在我正在构建的应用中使用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
参考:
答案 0 :(得分:5)
首先,first
和last
并不像您认为的那样简单:您完全忽略了limit
论证那些方法支持。
其次,scope
只是添加用于返回查询的类方法的一种奇特方式。您的范围滥用scope
,因为它们返回单个模型实例而不是查询。您根本不想使用scope
,而只是尝试替换first
和last
类方法,那么为什么不要覆盖他们?您需要正确覆盖它们,这需要阅读和理解Rails源代码,以便您正确模仿find_nth_with_limit
所做的事情。你想要覆盖second
,third
,......以及其他那些愚蠢的方法。
如果您不想替换first
和last
(IMO是一件好事),那么您可以根据需要添加默认范围来订购内容:
default_scope -> { order(:created_at) }
当然,默认范围带有它们自己的一组问题,并且在ORDER BY中偷偷摸摸,这可能会强迫您在实际想要指定ORDER BY时调用reorder
;请记住,多次调用order
会增加新的订购条件,但他们不会替换已经存在的订单。
我认为你这一切都错了。每当我看到M.first
时,我都会认为某些东西已被遗忘。按id
订购内容几乎没用,因此在使用first
和last
等方法之前,您应始终手动指定所需的订单。
答案 1 :(得分:1)
Rails 6(当前为6.0.0rc1版本)将通过implicit_order_column进行救援!
要按http://www.google.com/
订购并让created_at
,.first
,.last
等尊重,就很简单:
.second
答案 2 :(得分:0)
将 id
替换为 uuid
后,我在关联分配外键的方式上遇到了一些奇怪的问题,并不是 .last
和 .first
,而是因为我只是忘记使用 uuid 将 default: 'gen_random_uuid()'
添加到其中一个表中。一旦我解决了这个问题,问题就解决了。
create_table :appointments, id: :uuid, default: 'gen_random_uuid()' do |t|