Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>A year ago <a href="http://alicebobandmallory.com/articles/2009/11/02/comparing-instance-variables-in-ruby" rel="nofollow">I monkey patched</a> a kind of cryptic <code>instance_variables_compare</code> on <code>Object</code>. I guess you could use that.</p> <pre><code>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 </code></pre> <p><strong>A cheesy example</strong></p> <pre><code>require 'Date' class Cheese attr_accessor :name, :weight, :expire_date def initialize(name, weight, expire_date) @name, @weight, @expire_date = name, weight, expire_date end end stilton=Cheese.new('Stilton', 250, Date.parse("2010-12-02")) gorgonzola=Cheese.new('Gorgonzola', 250, Date.parse("2010-12-17")) </code></pre> <p><strong>irb is my weapon of choice</strong></p> <pre><code>&gt;&gt; stilton.instance_variables_compare(gorgonzola) =&gt; {"@name"=&gt;"Gorgonzola", "@expire_date"=&gt;#&lt;Date: 4910305/2,0,2299161&gt;} &gt;&gt; gorgonzola.instance_variables_compare(stilton) =&gt; {"@name"=&gt;"Stilton", "@expire_date"=&gt;#&lt;Date: 4910275/2,0,2299161&gt;} &gt;&gt; stilton.expire_date=gorgonzola.expire_date =&gt; #&lt;Date: 4910305/2,0,2299161&gt; &gt;&gt; stilton.instance_variables_compare(gorgonzola) =&gt; {"@name"=&gt;"Gorgonzola"} &gt;&gt; stilton.instance_variables_compare(stilton) =&gt; {} </code></pre> <p>As you can see the <code>instance_variables_compare</code> returns an empty Hash if the two objects has the same content.</p> <p><strong>An array of cheese</strong></p> <pre><code>stilton2=Cheese.new('Stilton', 210, Date.parse("2010-12-02")) gorgonzola2=Cheese.new('Gorgonzola', 250, Date.parse("2010-12-17")) arr=[]&lt;&lt;stilton&lt;&lt;stilton2&lt;&lt;gorgonzola&lt;&lt;gorgonzola2 </code></pre> <p><strong>One hash without problems and one with</strong></p> <pre><code>h={} problems=Hash.new([]) arr.each {|c| if h.has_key?(c.name) if problems.has_key?(c.name) problems[c.name]=problems[c.name]&lt;&lt;c elsif h[c.name].instance_variables_compare(c) != {} problems[c.name]=problems[c.name]&lt;&lt;c&lt;&lt;h[c.name] h.delete(c.name) end else h[c.name]=c end } </code></pre> <p>Now the Hash <code>h</code> contains the objects without merging problems and the <code>problems</code> hash contains those that has instance variables that differs.</p> <pre><code>&gt;&gt; h =&gt; {"Gorgonzola"=&gt;#&lt;Cheese:0xb375e8 @name="Gorgonzola", @weight=250, @expire_date=#&lt;Date: 2010-12-17 (4911095/2,0,2299161)&gt;&gt;} &gt;&gt; problems =&gt; {"Stilton"=&gt;[#&lt;Cheese:0xf54c30 @name="Stilton", @weight=210, @expire_date=#&lt;Date: 2010-12-02 (4911065/2,0,2299161)&gt;&gt;, #&lt;Cheese:0xfdeca8 @name="Stilton", @weight=250,@expire_date=#&lt;Date: 2010-12-02 (4911065/2,0,2299161)&gt;&gt;]} </code></pre> <p>As far as I can see you will not have to modify this code at all to support an array of <code>UserInfo</code> objects.</p> <p>It would most probably be much faster to compare the properties directly or with a override of <code>==</code>. This is how you override <code>==</code></p> <pre><code>def ==(other) return self.weight == other.weight &amp;&amp; self.expire_date == other.expire_date end </code></pre> <p>and the loop changes into this</p> <pre><code>arr.each {|c| if h.has_key?(c.name) if problems.has_key?(c.name) problems[c.name]=problems[c.name]&lt;&lt;c elsif h[c.name] != c problems[c.name]=problems[c.name]&lt;&lt;c&lt;&lt;h[c.name] h.delete(c.name) end else h[c.name]=c end } </code></pre> <p>Finally you might want to convert the <code>Hash</code> back to an <code>Array</code></p> <pre><code>result = h.values </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload