From: Robert Klemme Date: 2005-06-02T18:55:23+09:00 Subject: Re: Implementing a Read-Only array Gavin Kistner wrote: > On Jun 1, 2005, at 4:11 PM, Brian Schr�der wrote: >>> Gavin Kistner wrote: >>>>>> affectors = %w| << []= clear concat delete delete_at delete_if >>>>>> fill flatten! insert map! pack pop push reject! replace reverse! >>>>>> shift slice! sort! uniq! unshift | >> >> Though this means that you have to override all methods that can >> change the array. I'd shurely forget something in this case. You >> forgot e.g. #clear. Therefore I'd propose to explicitly delegate the >> needed methods for the application because this is easier to control. > > But again, that way prevents users' convenience methods for Arrays/ > Enumerables from being available. Yeah, I prefer the method to explicitely exclude mutators, too. The reason being that IMHO there are more often non modifying convenience methods defined on Array than modifying methods. > The 'affectors' list above is (I believe) precisely the list of > methods that can change the array. (Except I accidentally included > pack, which is non-mutating.) > > The final solution that I'm currently using is: > > require 'delegate' > > class ReadOnlyArray < DelegateClass(Array) > mutators = %w| << []= clear concat delete delete_at delete_if > fill | > mutators.concat %w| flatten! insert map! pop push reject! > replace | mutators.concat %w| reverse! shift slice! sort! uniq! > unshift | mutators.each do |name| > define_method( name ){ raise "#{self} is read-only!" } > end > end You don't even need the variable and the ugly concat require 'delegate' class ReadOnlyArray < DelegateClass(Array) %w{ << []= clear concat delete delete_at delete_if fill flatten! insert map! pop push reject! replace reverse! shift slice! sort! uniq! unshift }.each do |name| define_method( name ){ raise "#{self} is read-only!" } end end Kind regards robert