这是一个非常糟糕的方法,它根据代码检查相等性,但不区分大小写
def ==(another_country)
(code.nil? ? nil : code.downcase) == (another_country.code.nil? ? nil : another_country.code.downcase) unless another_country.nil?
end
你能指出我正确的方向如何写这个更优雅的w / o在丑陋的if else结构上吗?
# Country model
class Country < ActiveRecord::Base
attr_accessible :code
def ==(another_country)
code.to_s.downcase == another_country.code.to_s.downcase rescue false
end
end
广泛的测试:
# 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
答案 0 :(得分:1)
如果您使用的是Rails:
def ==(another_country)
return nil unless another_country
code.try(:downcase) == another_country.code.try(:downcase)
end
答案 1 :(得分:1)
nil有一个to_s方法:
def ==(another_country)
#return nil if another_country.nil?
self.code.to_s.downcase == another_country.code.to_s.downcase
end
答案 2 :(得分:1)
也许您可以将逻辑分解为两个方法,一个返回对象的标识,另一个方法用于检查相等性:
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
答案 3 :(得分:1)
由于任何非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
答案 4 :(得分:1)
这个怎么样,
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
,another_country
或another_country.code
中的任何一个为零,则会出现异常,rescue false
语句将返回false
值。< / p>
如果一切顺利,将进行比较,并根据输入返回true or false
。
答案 5 :(得分:0)
def == (another_country)
if code.nil? || another_country.nil? || another_country.code.nil?
return nil
end
code.downcase == another_country.code.downcase
end
通过这种方式,您可以一目了然地看到自己在做什么 - 无需检查和比较。
答案 6 :(得分:0)
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
如果您最终得到一组混合类型,则类检查是一种很好的做法。
如果您不担心''vs nil的情况,可以将其压缩一下以下。我不认为这是值得的。
def == (another_country)
code.try(:casecmp, another_country.code.to_s).try(:zero?) if another_country.is_a?(Country)
end
注意,如果你要覆盖==你还应该覆盖eql?并且哈希,否则你可以使用哈希和可枚举的方法获得意想不到的结果。