# Array#modified

**URL:** <https://www.ruby-forum.com/t/array-modified/81824>\
**Category:** Ruby\
**Created:** [January 15, 2007, 2:52pm UTC](https://www.ruby-forum.com/t/array-modified/81824 "2007-01-15T14:52:31Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![juozas](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/c2a13f/32.png) [@juozas](https://www.ruby-forum.com/u/juozas)\
**Post date:** [January 15, 2007, 2:52pm UTC](https://www.ruby-forum.com/t/array-modified/81824/1 "2007-01-15T14:52:31Z")

</div>

I’m looking for a simple and short solution/library that does this:

a = []

def a.modified  
puts “Array a changed”  
end

a \<\< ‘x’  
puts a  
a[0] = ‘y’  
puts a

----OUTPUT----  
Array a changed  
x  
Array a changed  
y

---

<div class="post-metadata">

**Author:** ![juozas](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/c2a13f/32.png) [@juozas](https://www.ruby-forum.com/u/juozas)\
**Post date:** [January 15, 2007, 3:04pm UTC](https://www.ruby-forum.com/t/array-modified/81824/2 "2007-01-15T15:04:22Z")

</div>

Juozas G. wrote:

> I’m looking for a simple and short solution/library that does this:  
> (snip)  
> ----OUTPUT----  
> Array a changed  
> x  
> Array a changed  
> y

Check out the Observable class in the standard library.

---

<div class="post-metadata">

**Author:** ![juozas](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/c2a13f/32.png) [@juozas](https://www.ruby-forum.com/u/juozas)\
**Post date:** [January 15, 2007, 3:20pm UTC](https://www.ruby-forum.com/t/array-modified/81824/3 "2007-01-15T15:20:30Z")

</div>

Tim H. wrote:

> Juozas G. wrote:
> 
> > I’m looking for a simple and short solution/library that does this:  
> > (snip)  
> > ----OUTPUT----  
> > Array a changed  
> > x  
> > Array a changed  
> > y
> 
> Check out the Observable class in the standard library.

Thanks for your prompt reply. Unfortunately Observable is not what I’m  
looking for. It requires manually setting “changed” state to true on  
every operation that modifies the array. I’m looking for something that  
overrides all of the methods that can modify an array (\<\<, pop, shift,  
push, []=, filter, etc.) then calls the old method and finally invokes  
the “modified” callback.

I’m assuming something like this exists (specifically for the Array  
class). I could write it myself, but I’d prefer to reuse existing code.

---

<div class="post-metadata">

**Author:** ![juozas](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/c2a13f/32.png) [@juozas](https://www.ruby-forum.com/u/juozas)\
**Post date:** [January 15, 2007, 4:31pm UTC](https://www.ruby-forum.com/t/array-modified/81824/4 "2007-01-15T16:31:43Z")

</div>

“I’m assuming something like this exists (specifically for the Array  
class). I could write it myself, but I’d prefer to reuse existing code.”

Ok, I dont know myself, but there seems to exist a very  
small “event” based … uhm thing, made possible in an easy  
manner already, like so

def StdLiving.inherited(sub)

Sure, its not what you need though. 🙂

I’d love to get event states from classes like Array in this case,  
would remind me a bit of the basic GUI state-events, like  
button\_pressed … or value\_changed 😉

PS: I think there exists a bigger event framework for Ruby too  
though… havent checked it yet so cant tell anything

---

<div class="post-metadata">

**Author:** ![juozas](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/c2a13f/32.png) [@juozas](https://www.ruby-forum.com/u/juozas)\
**Post date:** [January 15, 2007, 6:06pm UTC](https://www.ruby-forum.com/t/array-modified/81824/5 "2007-01-15T18:06:27Z")

</div>

> > 
> 
> class Changed  
> def initialize(obj, &changed)  
> @obj = obj  
> @changed = changed  
> end
> 
> def method\_missing(id, \*a, &b)  
> obj\_before = @obj.clone  
> @obj. **send** (id, \*a, &b)  
> if obj\_before != @obj  
> @changed[@obj, id, a, b]  
> end  
> end  
> end

I like this solution because it’s short. However, it requires cloning  
the array every time a method is invoked on it, it seems that it would  
slow it down too much for my needs. I’m not sure.

I think I’ll google for “ruby event framework” as Marc suggested.

---

<div class="post-metadata">

**Author:** ![juozas](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/c2a13f/32.png) [@juozas](https://www.ruby-forum.com/u/juozas)\
**Post date:** [January 15, 2007, 6:54pm UTC](https://www.ruby-forum.com/t/array-modified/81824/6 "2007-01-15T18:54:17Z")

</div>

> Juozas G. wrote:
> 
> …, but I’d prefer to reuse existing code.

Maybe also check out some design patterns (state pattern, observer  
pattern):

[http://rightfootin.blogspot.com/2006/08/implementing-state-pattern-in-ruby.html](http://rightfootin.blogspot.com/2006/08/implementing-state-pattern-in-ruby.html)

[http://cwilliams.textdriven.com/articles/2006/11/02/patterns-in-ruby-observer-pattern](http://cwilliams.textdriven.com/articles/2006/11/02/patterns-in-ruby-observer-pattern)

Cheers,  
verno

---

<div class="post-metadata">

**Author:** ![juozas](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/c2a13f/32.png) [@juozas](https://www.ruby-forum.com/u/juozas)\
**Post date:** [January 15, 2007, 5:11pm UTC](https://www.ruby-forum.com/t/array-modified/81824/7 "2007-01-15T17:11:07Z")

</div>

Juozas G. wrote:

> a[0] = ‘y’  
> puts a
> 
> ----OUTPUT----  
> Array a changed  
> x  
> Array a changed  
> y

class Changed  
def initialize(obj, &changed)  
@obj = obj  
@changed = changed  
end

def method\_missing(id, \*a, &b)  
obj\_before = @obj.clone  
@obj. **send** (id, \*a, &b)  
if obj\_before != @obj  
@changed[@obj, id, a, b]  
end  
end  
end

if $0 == **FILE**  
a = []  
c = Changed.new(a) do |obj, id, args, block|  
STDOUT \<\< “#{obj.inspect} changed by #{id}”  
STDOUT \<\< “(#{args.map { |x| x.inspect } \* ‘,’})” unless args.empty?  
STDOUT \<\< “\n”  
end  
c \<\< 1

# [1] changed by \<\<(1)

c.to\_s  
c \<\< 2

# [1, 2] changed by \<\<(2)

c.delete 2

# [1] changed by delete(2)

c.delete 2  
c \<\< 3

# [1, 3] changed by \<\<(3)

c[0] = 4

# [4, 3] changed by []=(0,4)

c.replace [6,6,6]

# [6, 6, 6] changed by replace([6, 6, 6])

c.clear

# [] changed by clear

end

---

<div class="post-metadata">

**Author:** ![juozas](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/c2a13f/32.png) [@juozas](https://www.ruby-forum.com/u/juozas)\
**Post date:** [January 19, 2007, 4:31pm UTC](https://www.ruby-forum.com/t/array-modified/81824/8 "2007-01-19T16:31:42Z")

</div>

On Mon, Jan 15, 2007 at 10:52:37PM +0900, Juozas G. wrote:

> a[0] = ‘y’  
> puts a
> 
> ----OUTPUT----  
> Array a changed  
> x  
> Array a changed  
> y

You can sort of do this, but an object does not know what variable(s) it  
is  
assigned to, so you will never be able to get the “Array a changed”  
message  
from it directly. Try the following, however:

module ArrayWatch  
def is\_modified?  
@modified  
end

def reset\_modified  
@modified = false  
end

def []=(k, v)  
@modified = true  
super(k, v)  
end

def \<\<(v)  
@modified = true  
super(v)  
end

def concat(v)  
@modified = true  
super(v)  
end

def push(\*v)  
@modified = true  
super(\*v)  
end

def unshift(\*v)  
@modified = true  
super(\*v)  
end

def replace(v)  
@modified = true  
super(v)  
end

def slice!(\*v)  
@modified = true  
super(\*v)  
end

def compact!  
@modified = true  
super  
end

def sort!(&block)  
@modified = true  
super &block  
end

def uniq!  
@modified = true  
super  
end

def reverse!  
@modified = true  
super  
end

def flatten!  
@modified = true  
super  
end

def collect!(&block)  
@modified = true  
super &block  
end

def map!(&block)  
@modified = true  
super &block  
end

def delete\_at(i)  
@modified = true  
super(i)  
end

def delete(v, &block)  
@modified = true  
super(v, &block)  
end

def delete\_if(&block)  
@modified = true  
super &block  
end

def reject!(&block)  
@modified = true  
super &block  
end

def shift  
@modified = true  
super  
end

def pop  
@modified = true  
super  
end

end

a = []  
a.extend ArrayWatch

def a.to\_s  
“a #{ is\_modified? ? ‘is’ : ‘is not’ } modified”  
end

puts a  
a \<\< ‘x’  
puts a  
a.reset\_modified  
puts a  
a[0] = ‘y’  
puts a

–Greg

---

<div class="post-metadata">

**Author:** ![juozas](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/c2a13f/32.png) [@juozas](https://www.ruby-forum.com/u/juozas)\
**Post date:** [January 19, 2007, 4:31pm UTC](https://www.ruby-forum.com/t/array-modified/81824/9 "2007-01-19T16:31:46Z")

</div>

On 15.01.2007 15:20, Gregory S. wrote:

> > puts a  
> > assigned to, so you will never be able to get the “Array a changed” message  
> > from it directly. Try the following, however:
> 
> module ArrayWatch  
> def is\_modified?  
> @modified  
> end  
> …

Alternative approach would be to use Delegator to wrap an Array  
instance.

OP, what are you trying to achieve? What is the problem you are trying  
to solve?

Kind regards

robert
