Modify only a .rb file, but not other .rb files, while still extending core classes?

Given is a small .rb file.

In that .rb file, class Array is modified and a convenience
method is added.

class Array

  def rand

I want to limit this modification to only that specific
.rb file though.

When I use that .rb file in a larger project, I do not want
the modification of class Array to leak out into other .rb
files. Is there a way to limit the scope of the modification?

Of course I can define a method simply and call that, but:

  array.rand

Looks better to my eyes than:

  rand(array)

So I would prefer to be able to do only the array.rand.

···

--
Posted via http://www.ruby-forum.com/.

One solution would be to create a module with the rand method, and
extend only the arrays you use in that .rb:

# small.rb

module Randomizable
  def rand
     # your implentation
  end
end

some_elements = [1,2,3,4,5]
some_elements.extend(Randomizable)
some_elements.rand

All other arrays in the system will not be affected.

Jesus.

···

On Wed, Oct 26, 2011 at 4:04 PM, Marc Heiler <shevegen@linuxmail.org> wrote:

Given is a small .rb file.

In that .rb file, class Array is modified and a convenience
method is added.

class Array

def rand

I want to limit this modification to only that specific
.rb file though.

When I use that .rb file in a larger project, I do not want
the modification of class Array to leak out into other .rb
files. Is there a way to limit the scope of the modification?

Of course I can define a method simply and call that, but:

array.rand

Looks better to my eyes than:

rand(array)

So I would prefer to be able to do only the array.rand.

Things like that will be available in Ruby 2.0, but aren't available yet (
http://yehudakatz.com/2010/11/30/ruby-2-0-refinements-in-practice/\)

···

On Wed, Oct 26, 2011 at 9:04 AM, Marc Heiler <shevegen@linuxmail.org> wrote:

Given is a small .rb file.

In that .rb file, class Array is modified and a convenience
method is added.

class Array

def rand

I want to limit this modification to only that specific
.rb file though.

When I use that .rb file in a larger project, I do not want
the modification of class Array to leak out into other .rb
files. Is there a way to limit the scope of the modification?

Of course I can define a method simply and call that, but:

array.rand

Looks better to my eyes than:

rand(array)

So I would prefer to be able to do only the array.rand.

--
Posted via http://www.ruby-forum.com/\.

I think an equivalent way is to directly open the singleton class of a
(what extend is doing in your implementation).

peterv@ASUS:~$ irb
001:0> a = [1,2,3,4,5]
=> [1, 2, 3, 4, 5]
002:0> class << a
003:1> def rand
004:2> self.sort_by!{|e| Kernel.rand} # without the Kernel reference,
infinite loop is created
005:2> end
006:1> end
=> nil
007:0> a.rand
=> [4, 1, 5, 3, 2]
008:0> b = [6,7,8,9,10]
=> [6, 7, 8, 9, 10]
009:0> Array.methods.grep(/rand/)
=>
010:0> a.methods.grep(/rand/)
=> [:rand]
011:0> b.methods.grep(/rand/)
=>

HTH,

Peter

···

2011/10/26 Jesús Gabriel y Galán <jgabrielygalan@gmail.com>

On Wed, Oct 26, 2011 at 4:04 PM, Marc Heiler <shevegen@linuxmail.org> > wrote:
> Given is a small .rb file.
>
> In that .rb file, class Array is modified and a convenience
> method is added.
>
> class Array
>
> def rand
>
> I want to limit this modification to only that specific
> .rb file though.
>
> When I use that .rb file in a larger project, I do not want
> the modification of class Array to leak out into other .rb
> files. Is there a way to limit the scope of the modification?
>
> Of course I can define a method simply and call that, but:
>
> array.rand
>
> Looks better to my eyes than:
>
> rand(array)
>
> So I would prefer to be able to do only the array.rand.

One solution would be to create a module with the rand method, and
extend only the arrays you use in that .rb:

# small.rb

module Randomizable
def rand
    # your implentation
end
end

some_elements = [1,2,3,4,5]
some_elements.extend(Randomizable)
some_elements.rand

All other arrays in the system will not be affected.

Jesus.

Sure, but if you need it in several arrays, the module approach is cleaner.
And I'd say that even for one array is cleaner too :).

Jesus.

···

On Wed, Oct 26, 2011 at 4:28 PM, Peter Vandenabeele <peter@vandenabeele.com> wrote:

2011/10/26 Jesús Gabriel y Galán <jgabrielygalan@gmail.com>

On Wed, Oct 26, 2011 at 4:04 PM, Marc Heiler <shevegen@linuxmail.org> >> wrote:
> Given is a small .rb file.
>
> In that .rb file, class Array is modified and a convenience
> method is added.
>
> class Array
>
> def rand
>
> I want to limit this modification to only that specific
> .rb file though.
>
> When I use that .rb file in a larger project, I do not want
> the modification of class Array to leak out into other .rb
> files. Is there a way to limit the scope of the modification?
>
> Of course I can define a method simply and call that, but:
>
> array.rand
>
> Looks better to my eyes than:
>
> rand(array)
>
> So I would prefer to be able to do only the array.rand.

One solution would be to create a module with the rand method, and
extend only the arrays you use in that .rb:

# small.rb

module Randomizable
def rand
# your implentation
end
end

some_elements = [1,2,3,4,5]
some_elements.extend(Randomizable)
some_elements.rand

All other arrays in the system will not be affected.

Jesus.

I think an equivalent way is to directly open the singleton class of a
(what extend is doing in your implementation).

Not only that: I'd expect it to use less resources, too. Reason is
that there is just one definition of the method. Plus, it's easier to
later change it for all Array instances if that should be needed.

Marc, we do not know what your method #rand does and which Ruby
version you are using, but since 1.9 there is Array#sample which might
be exactly what you are looking for.

Kind regards

robert

···

2011/10/26 Jesús Gabriel y Galán <jgabrielygalan@gmail.com>:

On Wed, Oct 26, 2011 at 4:28 PM, Peter Vandenabeele > <peter@vandenabeele.com> wrote:

2011/10/26 Jesús Gabriel y Galán <jgabrielygalan@gmail.com>

I think an equivalent way is to directly open the singleton class of a
(what extend is doing in your implementation).

Sure, but if you need it in several arrays, the module approach is cleaner.
And I'd say that even for one array is cleaner too :).

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Agreed.

I just thought that maybe it was easier to understand the concept of a
singleton
class of an object in isolation "change only the behavior of this instance,
not
of the class or of other instances of the class", without adding the
difference
between Module include and extend into the example.

HTH,

Peter

···

2011/10/26 Jesús Gabriel y Galán <jgabrielygalan@gmail.com>

On Wed, Oct 26, 2011 at 4:28 PM, Peter Vandenabeele > <peter@vandenabeele.com> wrote:
> 2011/10/26 Jesús Gabriel y Galán <jgabrielygalan@gmail.com>
>
>> On Wed, Oct 26, 2011 at 4:04 PM, Marc Heiler <shevegen@linuxmail.org> > >> wrote:
>> > Given is a small .rb file.
>> >
>> > In that .rb file, class Array is modified and a convenience
>> > method is added.
>> >
>> > class Array
>> >
>> > def rand
>> >
>> > I want to limit this modification to only that specific
>> > .rb file though.
>> >
>> > When I use that .rb file in a larger project, I do not want
>> > the modification of class Array to leak out into other .rb
>> > files. Is there a way to limit the scope of the modification?
>> >
>> > Of course I can define a method simply and call that, but:
>> >
>> > array.rand
>> >
>> > Looks better to my eyes than:
>> >
>> > rand(array)
>> >
>> > So I would prefer to be able to do only the array.rand.
>>
>> One solution would be to create a module with the rand method, and
>> extend only the arrays you use in that .rb:
>>
>> # small.rb
>>
>> module Randomizable
>> def rand
>> # your implentation
>> end
>> end
>>
>> some_elements = [1,2,3,4,5]
>> some_elements.extend(Randomizable)
>> some_elements.rand
>>
>> All other arrays in the system will not be affected.
>>
>> Jesus.
>>
>
>
> I think an equivalent way is to directly open the singleton class of a
> (what extend is doing in your implementation).

Sure, but if you need it in several arrays, the module approach is cleaner.
And I'd say that even for one array is cleaner too :).

On an unrelated note, if you want a random element from an array,
there's already a method for that, Array#sample. (or #choice in
1.8.7).

-- Matma Rex