Ruby 基于一个属性的不区分大小写的equals方法 原始问题
这是一个非常可怕的方法,它在代码的基础上检查是否相等,但不区分大小写Ruby 基于一个属性的不区分大小写的equals方法 原始问题,ruby,boolean-logic,Ruby,Boolean Logic,这是一个非常可怕的方法,它在代码的基础上检查是否相等,但不区分大小写 def ==(another_country) (code.nil? ? nil : code.downcase) == (another_country.code.nil? ? nil : another_country.code.downcase) unless another_country.nil? end 你能为我指出正确的方向吗?如何在丑陋的if-else结构上写这个更优雅的w/o 这就是我最终使用的解决方
def ==(another_country)
(code.nil? ? nil : code.downcase) == (another_country.code.nil? ? nil : another_country.code.downcase) unless another_country.nil?
end
你能为我指出正确的方向吗?如何在丑陋的if-else结构上写这个更优雅的w/o
这就是我最终使用的解决方案(+rspec)
#国家/地区模式
类国家/地区
广泛测试:
# RSpec
describe Country do
describe 'equality based solely on Country.code' do
before do
@country_code_de = FactoryGirl.build(:country, :code => 'de')
end
it 'should be equal if Country.code is equal' do
other_country_code_de = FactoryGirl.build(:country, :code => 'de')
@country_code_de.should == other_country_code_de
end
it 'should be not equal if Country.code is not equal' do
country_code_usa = FactoryGirl.build(:country, :code => 'usa')
@country_code_de.should_not == country_code_usa
end
it 'should be case insensitive' do
country_code_de_uppercase = FactoryGirl.build(:country, :code => 'DE')
@country_code_de.should == country_code_de_uppercase
end
it 'should not rely on id for equality' do
@country_code_de.id = 0
country_code_usa = FactoryGirl.build(:country, :code => 'usa', :id => 0)
@country_code_de.should_not == country_code_usa
end
it 'should be not equal if Country.code of one Country is nil' do
country_code_nil = FactoryGirl.build(:country, :code => nil)
@country_code_de.should_not == country_code_nil
end
it 'should be equal if Country.code for both countries is nil' do
country_code_nil = FactoryGirl.build(:country, :code => nil)
other_country_code_nil = FactoryGirl.build(:country, :code => nil)
country_code_nil.should == other_country_code_nil
end
it 'should be not equal if other Country is nil' do
@country_code_de.should_not == nil
end
it 'should be not equal if other object is not a Country' do
@country_code_de.should_not == 'test'
end
it 'should be equal for descendants of Country with same Country.code' do
class CountryChild < Country
end
country_child = CountryChild.new(:code => 'de')
@country_code_de.should == country_child
end
end
end
#RSpec
描述国家做什么
描述“完全基于国家的平等。代码”是什么
在做之前
@country\u code\u de=FactoryGirl.build(:country,:code=>'de')
终止
“如果Country.code相等,则应相等”do
其他国家/地区\u代码\u de=FactoryGirl.build(:country,:code=>de)
@国家/地区代码应==其他国家/地区代码
终止
“如果Country.code不相等,则不应相等”do
country\u code\u usa=FactoryGirl.build(:country,:code=>“usa”)
@国家代码不应=国家代码美国
终止
它“应该不区分大小写”吗
country\u code\u de\u大写=FactoryGirl.build(:country,:code=>'de')
@country_code_de.should==country_code_de_大写
终止
它“不应该依赖id来实现平等”吗
@国家代码id=0
country\u code\u usa=FactoryGirl.build(:country,:code=>'usa',:id=>0)
@国家代码不应=国家代码美国
终止
如果一个国家的Country.code为零,则“不应相等”do
country\u code\u nil=FactoryGirl.build(:country,:code=>nil)
@国家/地区代码不应=国家/地区代码无
终止
如果两个国家的Country.code均为零,则“应该相等”do
country\u code\u nil=FactoryGirl.build(:country,:code=>nil)
other\u country\u code\u nil=FactoryGirl.build(:country,:code=>nil)
国家/地区代码\u nil.should==其他国家/地区代码\u nil
终止
“如果其他国家为零,则不应平等”do
@国家/地区代码不应=零
终止
“如果其他对象不是一个国家,那么它就不应该是相等的”这样做吗
@国家/地区代码不应==“测试”
终止
“同一国家的后代应该是平等的。代码”do
类CountryChild'de')
@国家/地区代码应==国家/地区子项
终止
终止
终止
通过这种方式,您所做的操作一目了然—无检查和比较。如果您使用的是Rails:
def ==(another_country)
return nil unless another_country
code.try(:downcase) == another_country.code.try(:downcase)
end
nil有一个to_s方法:
def ==(another_country)
#return nil if another_country.nil?
self.code.to_s.downcase == another_country.code.to_s.downcase
end
也许您可以将逻辑分为两种方法,一种返回对象的标识,另一种用于检查相等性:
class MyClass
def identity
return nil if code.nil?
code.downcase
end
def ==(other)
return false unless other.is_a?(MyClass)
self.identity == other.identity
end
end
由于任何不是
nil
或false
的值在条件中的行为类似于true
,因此可以使用代码执行一些技巧
表情像
(code.nil? ? nil : code.downcase)
可以毫无痛苦地被
(code.downcase if code) # or by this one (code && code.downcase)
第二个
(do_something) unless another_country.nil?
和
(do_something) if another_country
# or
another_contry && (do_something)
所以最终你可以把你的方法变成这样
def ==(another_country)
code && another_country.code &&
code.downcase == another_country.code.downcase
end
一些测试
class Country
attr_accessor :code
def initialize(code)
@code = code
end
def ==(another_country)
code && another_country.code &&
code.downcase == another_country.code.downcase
end
end
p Country.new("FOObar") == Country.new("fooBAR") # => true
p Country.new(nil) == Country.new(nil) # => nil
p Country.new("XXX") == Country.new(nil) # => nil
p Country.new(nil) == Country.new("XXX") # => nil
这个怎么样,
def ==(another_country)
return false if code.blank? # Remove this line if you want to return true if code and antoher_country.code are nil
code.to_s.downcase == another_country.to_s.code.downcase rescue false
end
这里,如果code
、另一个国家或另一个国家/地区.code
中的任何一个为零,它将执行异常,并且rescue false
语句将返回false
值
如果一切顺利,将进行比较,并根据输入返回true或false
def == (another_country)
return unless another_country.is_a?(Country)
return if code.nil? || another_country.code.nil?
code.casecmp(another_country.code).zero?
end
如果最终得到一个混合类型数组,那么类检查是一种很好的做法
如果您不担心“”与nil的情况,可以将其压缩为以下内容。但我认为这不值得
def == (another_country)
code.try(:casecmp, another_country.code.to_s).try(:zero?) if another_country.is_a?(Country)
end
注意,如果您正在重写==您还应该重写eql吗?和散列,否则您可以使用散列和可枚举方法获得意外的结果
如果另一个国家的为nil
,会发生什么?我最后使用了另一个国家的nil?因为它与Rails无关,所以如果==
方法返回nil,我会非常惊讶,但是您是对的,OP的代码就是这样做的。编辑code@steenslag至少根据调试器,我的方法不会返回nil,是吗?我认为您缺少了一个返回值
。另外,从=
方法返回nil
有什么意义?我认为它应该总是返回一个布尔值。我只是在模仿他的原始表达式——它的末尾有一个除非<代码>除非为真,否则将导致nil
。如果
零件缺少退货,则返回“是”。对。添加了返回nil,除非另一个国家/地区作为方法的第一行。身份是否应该是私有的?我想这取决于具体情况。如果两个代码都是nil
,则您的解决方案不起作用。我从你的代码中学到了很多,我相信你把一个大问题分解成小问题的方法在将来会对我有用(+1)@visor:这是我迄今为止在SC上提出的最有成效的问题。我的问题的答案是我们能想出的最短答案,但答案中有很多智慧;)
def == (another_country)
return unless another_country.is_a?(Country)
return if code.nil? || another_country.code.nil?
code.casecmp(another_country.code).zero?
end
def == (another_country)
code.try(:casecmp, another_country.code.to_s).try(:zero?) if another_country.is_a?(Country)
end