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
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
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.
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
yCheck 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.
“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
class Changed
def initialize(obj, &changed)
@obj = obj
@changed = changed
enddef 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.
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://cwilliams.textdriven.com/articles/2006/11/02/patterns-in-ruby-observer-pattern
Cheers,
verno
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
c.to_s
c << 2
c.delete 2
c.delete 2
c << 3
c[0] = 4
c.replace [6,6,6]
c.clear
end
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
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
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.
Sponsor our Newsletter | Privacy Policy | Terms of Service | Remote Ruby Jobs