Ruby:获取对象之间不同属性的列表

时间:2009-10-30 07:29:23

标签: ruby introspection

直升机,

我是Ruby的新手(使用1.8.6)并且需要知道以下功能是否可以自动使用,如果没有,这将是实现它的最佳方法。

我有班车。 并有两个对象:

car_a and car_b

我有什么方法可以比较并找出其中一个对象与另一个对象相比有哪些属性?

例如,

car_a.color = 'Red'
car_a.sun_roof = true
car_a.wheels = 'Bridgestone'

car_b.color = 'Blue'
car_b.sun_roof = false
car_b.wheels = 'Bridgestone'

然后做一个

car_a.compare_with(car_b)

应该给我:

{:color => 'Blue', :sun_roof => 'false'}

或其他相似之处?

4 个答案:

答案 0 :(得分:7)

需要一些调整,但这是基本的想法:

module CompareIV
  def compare(other)
    h = {}
    self.instance_variables.each do |iv|
      print iv
      a, b = self.instance_variable_get(iv), other.instance_variable_get(iv)
      h[iv] = b if a != b
    end
    return h
  end
end

class A
  include CompareIV
  attr_accessor :foo, :bar, :baz

  def initialize(foo, bar, baz)
    @foo = foo
    @bar = bar
    @baz = baz
  end
end

a = A.new(foo = 1, bar = 2, baz = 3)
b = A.new(foo = 1, bar = 3, baz = 4)

p a.compare(b)

答案 1 :(得分:2)

怎么样

class Object
  def instance_variables_compare(o)
    Hash[*self.instance_variables.map {|v| 
      self.instance_variable_get(v)==o.instance_variable_get(v) ? [] : [v,o.instance_variable_get(v)]}.flatten]
  end
end


>> car_a.instance_variables_compare(car_b)
=> {"@color"=>"Blue", "@sun_roof"=>false}

答案 2 :(得分:0)

不确定是否可以立即获得属性的差异。但是周围的工作是尝试.eql?两个对象上的运算符

#for example, 

car_a.eql?(car_b)

#could test whether car_a and car_b have the same color, sunroof and wheels
#need to override this method in the Car class to be meaningful,otherwise it's the same as ==

如果存在差异,则可以使用Object Class的To_Array方法,如

car_a.to_a
car_b.to_a

现在比较两个数组差异很容易。

未经测试但

(car_a | car_b ) - ( car_a & car_b )

或类似的东西应该会给你不同的属性。

HTH

答案 3 :(得分:0)

我遇到了同样的问题,正在研究你的一些解决方案,但我认为Ruby必须有办法解决这个问题。我发现了ActiveModel :: Dirty。像魅力一样。

http://api.rubyonrails.org/classes/ActiveModel/Dirty.html#method-i-changes