Strange Array behavior after upgrading to Rails 2.0.2

I’ve come around a strange problem, after upgrading to 2.0.2.

I have subclassed the Array class with this method to extract a random
item (I haven’t made it myself, but it is quite clever):

class Array
def random(weights=nil)
return random(map {|n| n.send(weights)}) if weights.is_a? Symbol

puts length
puts self

weights ||= Array.new(length, 1.0)
total = weights.inject(0.0) {|t,w| t+w}
point = rand * total

zip(weights).each do |n,w|
  return n if w >= point
  point -= w
end

end
end

If I use it with a simple array like:

arr = [5,8,7,3]
arr.random

It works fine.

But if i try the same with a database extraction I now get an error. As
an example, I have a model called “Banner”:

banner_list = Banner.find(:all)
banner_list.random

This gives the following error:


undefined method `*’ for #Banner:0x489c3f4

The error occurs in the subclassing code at the following line:

point = rand * total

The strange thing is, that this has worked with Rails 1.2.5, but when
upgrading to 2.0.2, the error now occurs.

Does Rails 2.0.2 return results in another way than 1.2.5?

Sorry I’ve made a slight typo (I was trying to find out what was
happening…) The subclassing should look like this:

class Array
def random(weights=nil)
return random(map {|n| n.send(weights)}) if weights.is_a? Symbol

weights ||= Array.new(length, 1.0)
total = weights.inject(0.0) {|t,w| t+w}
point = rand * total

zip(weights).each do |n,w|
  return n if w >= point
  point -= w
end

end
end

Rick Denatale wrote:

I think that changing the line

point = rand * total

to

point = Kernel::rand * total

will fix this.

And indeed it did. Thank you very much! :slight_smile:

  • Carsten

On Dec 28, 2007 10:48 AM, Carsten G.
[email protected] wrote:

puts length
end
But if i try the same with a database extraction I now get an error. As
an example, I have a model called “Banner”:

banner_list = Banner.find(:all)
banner_list.random

This gives the following error:


undefined method `*’ for #Banner:0x489c3f4

ActiveSupport now adds an Array#rand method which returns a random
element, this overrides Kernel#rand which returns a float.

I think that changing the line

point = rand * total

to

point = Kernel::rand * total

will fix this.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

On Dec 28, 2007 4:27 PM, Mark W. [email protected] wrote:

And indeed it did. Thank you very much! :slight_smile:

Couldn’t you just use Array#rand ?

I thought of suggesting that, but he’s trying to do something similar,
but with a parameter to provide a weighted distribution. The rand
method in ActiveSupport only gives a uniform distribution.

It might be useful if this is only used with ActiveSupport to put
something like

return rand unless weightt

at the top of the method though.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

On Dec 28, 12:56 pm, Carsten G. <rails-mailing-l…@andreas-
s.net> wrote:

Rick Denatale wrote:

I think that changing the line
point = rand * total
to
point = Kernel::rand * total
will fix this.

And indeed it did. Thank you very much! :slight_smile:

Couldn’t you just use Array#rand ?

///ark

Rick Denatale wrote:

I thought of suggesting that, but he’s trying to do something similar,
but with a parameter to provide a weighted distribution. The rand
method in ActiveSupport only gives a uniform distribution.

It might be useful if this is only used with ActiveSupport to put
something like

return rand unless weightt

at the top of the method though.

You’re quite right Rick. The code could do with this refactoring, after
all it IS pre-2.0 :slight_smile: - thank you for your bright ideas.

I don’t recall who made this little nice function, but I think I’ll
repost it on the net with modifications.

  • Carsten