当我运行规范时,我收到以下错误:
.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/activemodel-4.2.5/lib/active_model/validations/callbacks.rb:26: warning: Comparable#== will no more rescue exceptions of #<=> in the next release.
.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/activemodel-4.2.5/lib/active_model/validations/callbacks.rb:26: warning: Return nil in #<=> if the comparison is inappropriate or avoid such comparison.
唯一的地方我&lt; =&gt;在我的一个模特中:
class PostCategory
CONTEXTS = %w(regular)
module Collections
def all
@all ||= AppConfig.post_categories.
map { |c| new(c) }.
sort
end
def in_context(context)
@all.select { |e| e.in_context?(context) }
end
end
extend Collections
include Comparable
attr_reader :name, :image_id
def initialize(hash)
@name = hash.fetch('name')
@image_id = hash.fetch('image_id')
@contexts = hash.fetch('contexts', CONTEXTS)
end
def <=>(other)
@name <=> other.name
end
end
我尝试在“def&lt; =&gt;(other)”之后添加下面的nil但是会产生排序问题。
答案 0 :(得分:4)
由于this Ruby issue中讨论的更改,会出现此警告。它的要点是:当一个类包含Comparable并调用其==
方法时,Comparable#==
依次调用<=>
方法。到目前为止,在Ruby版本中,如果<=>
引发错误,==
将吞下错误并返回false
。这很好,因为开发人员不希望==
引发错误,但这很糟糕,因为它可以隐藏<=>
的问题。在将来的版本中,==
将不再吞下<=>
引发的错误,因此会出现警告。
如果查看堆栈跟踪中提到的行上的Rails source,您可以看到错误的来源:
define_callbacks :validation,
terminator: ->(_,result) { result == false },
# ...
在您的情况下,result
是PostCategory类的一个实例。当上面的第二行调用result == false
时,您的<=>
方法会调用false.name
,这会引发错误(因为false
不响应name
)。< / p>
解决方案是Comparable docs说:
如果其他对象无法比较,则
<=>
运算符应返回nil
。
像这样修改你的方法:
def <=>(other)
return unless other.respond_to?(:name)
@name <=> other.name
end
或者,如果您希望PostCategory的实例仅与PostCategory的其他实例(而不是响应name
的任何实例)相比较:
def <=>(other)
return unless other.is_a?(self.class)
@name <=> other.name
end
答案 1 :(得分:0)
没有足够的细节来准确诊断问题,但以下是两个可以帮助您解决问题的提示。
•警告告诉您发动机救出<=>
时发生异常。好的,为了避免它,我们首先应该了解它是什么:
def <=>(other)
@name <=> other.name
rescue => e
puts e.inspect # or even e.backtrace
end
•现在,当你知道确切的问题是什么时,你可以优雅地处理它:
def <=>(other)
return nil unless @name.is_a?(String) && other.name.is_a?(String)
@name <=> other.name
end
希望它有所帮助。