DM 0.10.2 + bad version of extlib == suck

0 views
Skip to first unread message

Gary Yngve

unread,
Dec 14, 2009, 12:45:41 AM12/14/09
to me...@googlegroups.com
I just finished sleuthing a problem where DM 0.10.2 didn't work quite
right on nested associations, and it boiled down to LazyArray's map
getting inherited from Array instead of Enumerable, and the guilty
party was a bundled DM 0.9.14 gem that was not equal to the current DM
0.9.14 gem. Dunno where we got that bad gem from, or if we
monkey-patched it and rebuilt it ourselves months ago when going to
Merb 1.1 or DM 0.10.

Anyway, surprising how fragile DM's Collection is (when LazyArray
inherits map from Array, Collection's each is not called, whereas it
is when LazyArray inherits map from Enumerable), and how painful the
bug was to sleuth (i suppose i didn't have much better to do while
trying to get over a bad cold)

Hope no one else has to go through this.

-Gary

Dan Kubb (dkubb)

unread,
Dec 15, 2009, 3:07:11 AM12/15/09
to merb
Gary,

> Anyway, surprising how fragile DM's Collection is (when LazyArray
> inherits map from Array, Collection's each is not called, whereas it
> is when LazyArray inherits map from Enumerable), and how painful the
> bug was to sleuth (i suppose i didn't have much better to do while
> trying to get over a bad cold)

Could you explain a bit more about this problem? I'm not sure I
totally understand what the cause was, and how we can help prevent it
from happening again.

It is true that we simplified LazyArray somewhat, and made some
corresponding changes in DM::Collection to accommodate those changes,
but I released a new extlib and bumped the dependency in dm-core to
require it. I'm sure that attempting to mix and match older versions
of extlib with new versions of dm-core would give strange results. (I
presume you had an extlib built from git source prior to the LazyArray
refactoring?)

--

Dan
(dkubb)

Dan Kubb (dkubb)

unread,
Dec 15, 2009, 3:21:16 AM12/15/09
to merb
> It is true that we simplified LazyArray somewhat, and made some
> corresponding changes in DM::Collection to accommodate those changes,

A side note is that LazyArray is going to be extracted from extlib and
moved into dm-core for the next release, so (if I understand the
problem) we may be able to prevent this type of thing from
reoccurring. To my knowledge nothing else uses LazyArray besides DM,
so I don't expect this change to cause any issues with Merb.

--

Dan
(dkubb)

Gary Yngve

unread,
Dec 15, 2009, 7:50:32 PM12/15/09
to merb
Hi Dan,

It appears we were running an edge DM 0.9.14, possibly even patched up
a little bit by us as well (the tracking for that is gone because it
was bundled prior to saving in repo -- a mistake on our part), so when
we went to thor merb:gem:install, it never reinstalled the real DM
0.9.14 because the versioning looked the same.

Here is a diff for morbid curiousity (the /Library one is the real
extlib):

release> diff /Library/Ruby/Gems/1.8/gems/extlib-0.9.14/lib/extlib/
lazy_array.rb gems/gems/extlib-0.9.14/lib/extlib/lazy_array.rb
2c2
< include Enumerable
---
> instance_methods.each { |m| undef_method m unless %w[ __id__ __send__ send class dup object_id kind_of? respond_to? equal? assert_kind_of should should_not instance_variable_set instance_variable_get extend ].include?(m.to_s) }
85,89c85
< (@tail.nil? || @tail.empty?) &&
< (@head.nil? || @head.empty?) && begin
< lazy_load
< @array.empty?
< end
---
> !any?
408,417d403
< def each
< lazy_load
< if block_given?
< @array.each { |entry| yield entry }
< self
< else
< @array.each
< end
< end
<
436c422
< return false unless @head[i].__send__(operator, other[i])
---
> return false unless @head[i].send(operator, other[i])
443c429
< return false unless @tail[i].__send__(operator, other[i])
---
> return false unless @tail[i].send(operator, other[i])
450a437,456
>
> # add proxies for all remaining Array and Enumerable methods
> (Array.public_instance_methods(false) | Enumerable.public_instance_methods(false)).each do |method|
> next if public_method_defined?(method)
>
> target = if method.to_s[-1, 1] == '='
> "send(:#{method}, *args, &block)"
> else
> "#{method}(*args, &block)"
> end
>
> class_eval <<-RUBY, __FILE__, __LINE__ + 1
> public
> def #{method}(*args, &block) # def []=(*args, &block)
> lazy_load # lazy_load
> results = @array.#{target} # results = @array.send(:[]=, *args, &block)
> results.equal?(@array) ? self : results # results.equal?(@array) ? self : results
> end # end
> RUBY
> end
Reply all
Reply to author
Forward
0 new messages