Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DataMapper Stack-Level too deep bug with EmailAddress #4

Closed
postmodern opened this issue Apr 25, 2011 · 22 comments
Closed

DataMapper Stack-Level too deep bug with EmailAddress #4

postmodern opened this issue Apr 25, 2011 · 22 comments
Assignees
Labels
bug Bug Report datamapper DataMapper (legacy) model

Comments

@postmodern
Copy link
Member

After importing the first EmailAddress using ronin-emails --import=emails.txt (containing only alice@example.com), the email address cannot be queried.

>> UserName.first
 ~ (0.000128) SELECT "id", "name", "created_at" FROM "ronin_user_names" ORDER BY "id" LIMIT 1
=> #<Ronin::UserName:alice>
>> HostName.first
 ~ (0.000147) SELECT "id", "type", "address", "created_at" FROM "ronin_addresses" WHERE "type" IN ('Ronin::HostName') ORDER BY "id" LIMIT 1
=> #<Ronin::HostName: example.com>
>> EmailAddress.first
 ~ (0.000155) SELECT "id", "created_at" FROM "ronin_email_addresses" ORDER BY "id" LIMIT 1
 ~ (0.000129) SELECT "id", "user_name_id" FROM "ronin_email_addresses" WHERE "id" = 1 ORDER BY "id"
/home/hal/.rvm/gems/ruby-1.9.2-p180/gems/dm-core-1.1.0/lib/dm-core/support/subject_set.rb:212: stack level too deep (SystemStackError)

$ sqlite3 ~/.ronin/database.sqlite3 
SQLite version 3.6.23.1
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> select * from ronin_email_addresses;
1|1|1|2011-04-25T16:40:48-07:00
sqlite> .schema ronin_email_addresses
CREATE TABLE "ronin_email_addresses" ("id" INTEGER PRIMARY KEY AUTOINCREMENT, "user_name_id" INTEGER, "host_name_id" INTEGER, "created_at" TIMESTAMP);
CREATE UNIQUE INDEX "unique_index_ronin_email_addresses" ON "ronin_email_addresses" ("user_name_id", "host_name_id");
@ghost ghost assigned postmodern Apr 25, 2011
@dkubb
Copy link

dkubb commented Apr 28, 2011

@snusnu: This stack overflow error appears to be happening inside SubjectSet. Any idea what it could be?

@postmodern
Copy link
Member Author

Repro script:

require 'ruby-debug'

require 'bundler'
Bundler.setup(:development, :default)

require 'ronin/database'
require 'ronin/user_name'
require 'ronin/host_name'
require 'ronin/email_address'

Ronin::Database.setup

Ronin::EmailAddress.parse('alice@example.com').save

debugger
Ronin::EmailAddress.first.host_name

@postmodern
Copy link
Member Author

@solnic do you have any ideas about this bug? Me and @dkubb are stumped.

@solnic
Copy link

solnic commented Oct 14, 2011

@postmodern no idea, does it happen in 1.2.0 too?

@postmodern
Copy link
Member Author

@solnic, Yep still very reproducible.

@jfredett
Copy link

+1 I'm having this issue too.

@postmodern
Copy link
Member Author

Tested this again, against DataMapper 1.3.0.beta which now uses Virtus and got a clearer error:

>> DataMapper.finalize
=> DataMapper
>> email = EmailAddress.parse('alice@example.com')
=> #<Ronin::EmailAddress: alice@example.com>
>> email.save
=> true
>> EmailAddress.first
 ~ (0.000120) SELECT "id", "created_at", "user_name_id", "host_name_id" FROM "ronin_email_addresses" ORDER BY "id" LIMIT 1
/home/hal/.rvm/gems/ruby-1.9.3-p125/gems/virtus-0.2.0/lib/virtus/coercion.rb:28: stack level too deep (SystemStackError)

@jfredett
Copy link

Where/how/with what magic can I use to get 1.3.0.beta. I'd like to try it against my bug and see if it resolves/gives me a better error. The usual "shove it in Gemfile" isn't working.

@postmodern
Copy link
Member Author

I just pushed the dm-edge branch which uses DM 1.3.0.beta from git:

git clone git://github.com/ronin-ruby/ronin.git -b dm-edge
cd ronin/
bundle install
./bin/ronin

@jfredett
Copy link

Doesn't seem to fix it. Same output change as yours. Bug is just coming from virtus now.

I'll keep tuned.

@postmodern
Copy link
Member Author

Here's the script I'm using with Ruby 1.9's builtin debugger:

require 'ronin'
require 'ronin/email_address'

DataMapper.finalize

email = Ronin::EmailAddress.first

require 'debug'
email.to_s

exit

@postmodern
Copy link
Member Author

After running the debug script, it seems something (maybe dm-validations) is infinitely walking the relationships from Ronin::EmailAddress. I think Ruby might be incorrectly pegging virtus as the source of the cycle in the call-graph?

@solnic @dkubb do you have time to look into this again?

@postmodern
Copy link
Member Author

Updated the test script:

require 'bundler'
Bundler.setup

require 'ronin/database'
require 'ronin/host_name'
require 'ronin/user_name'
require 'ronin/email_address'

Ronin::Database.setup

puts "Querying EmailAddress ..."
email = Ronin::EmailAddress.first

puts "Accessing user_name ..."
email.user_name.name

puts "Accessing host_name ..."
email.host_name.name

puts "Done"
exit
Querying EmailAddress ...
 ~ (0.000104) SELECT "id", "created_at", "user_name_id", "host_name_id" FROM "ronin_email_addresses" ORDER BY "id" LIMIT 1
Accessing user_name ...
/home/hal/.rvm/gems/ruby-1.9.3-p125/bundler/gems/dm-core-14246fb8fe0a/lib/dm-core/query/conditions/comparison.rb:492: stack level too deep (SystemStackError)

The good news is, this only seems to effect the relationships of EmailAddress objects. Username.first and HostName.first behave as expected.

@dkubb
Copy link

dkubb commented Mar 28, 2012

@postmodern yeah, I've noticed that MRI sometimes incorrectly identifies the source of a StackOverflowError and reports a line of code that couldn't possibly be the source of the problem. Often when I see that I'll test with Rubinius which has a bit nicer stacktrace in some cases. I may also narrow it down by testing with JRuby too.

Is there a gist somewhere that reproduces this problem, something I can checkout and run bundle install on, then run a script? I'm unfamiliar with the details of ronin and which dependencies are needed to repro this.

@postmodern
Copy link
Member Author

@dkubb Ah that's a good idea, I'll test on JRuby/Rubinius. In order to repro, simply clone the repository (the dm-edge branch bundles DataMapper edge), run bundle install, then run this script in the root of the project: https://gist.github.com/2223911

The script will require the related models and Ronin::Database.setup also calls DataMapper.finalize. If you specify the DEBUG environment variable, you can see DataMapper::Logger output.

Unfortunately, I haven't been able to create a standalone script for this bug, since I'm not exactly sure what triggers the bug. I suspect it might be related to STI models (Ronin::HostName inherits from Ronin::Address), although I haven't been able to repro this with similar models using dm-bug_report.

@postmodern
Copy link
Member Author

@dkubb Just ran the script under JRuby and got a better stacktrace:

>>> Saving email address ...
SystemStackError: stack level too deep
              scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/repository.rb:114
              scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/repository.rb:113
          query_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/relationship.rb:153
       resource_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:107
          lazy_load at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:191
          lazy_load at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/resource/persistence_state/persisted.rb:23
                get at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/resource/persistence_state/persisted.rb:8
          user_name at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/model/relationship.rb:351
             to_ary at /vault/1/code/ronin/ronin/lib/ronin/email_address.rb:278
              Array at org/jruby/RubyKernel.java:327
  target_conditions at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/query.rb:56
       source_scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:89
          query_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/relationship.rb:156
              scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/repository.rb:114
              scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/repository.rb:113
          query_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/relationship.rb:153
       resource_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:107
          lazy_load at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:191
          lazy_load at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/resource/persistence_state/persisted.rb:23
                get at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/resource/persistence_state/persisted.rb:8
          user_name at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/model/relationship.rb:351
             to_ary at /vault/1/code/ronin/ronin/lib/ronin/email_address.rb:278
              Array at org/jruby/RubyKernel.java:327
  target_conditions at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/query.rb:56
       source_scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:89
          query_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/relationship.rb:156
              scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/repository.rb:114
              scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/repository.rb:113
          query_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/relationship.rb:153
       resource_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:107
          lazy_load at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:191
          lazy_load at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/resource/persistence_state/persisted.rb:23
                get at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/resource/persistence_state/persisted.rb:8
          user_name at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/model/relationship.rb:351
             to_ary at /vault/1/code/ronin/ronin/lib/ronin/email_address.rb:278
              Array at org/jruby/RubyKernel.java:327
  target_conditions at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/query.rb:56
       source_scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:89
          query_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/relationship.rb:156
              scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/repository.rb:114
              scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/repository.rb:113
          query_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/relationship.rb:153
       resource_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:107
          lazy_load at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:191
          lazy_load at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/resource/persistence_state/persisted.rb:23
                get at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/resource/persistence_state/persisted.rb:8
          user_name at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/model/relationship.rb:351
             to_ary at /vault/1/code/ronin/ronin/lib/ronin/email_address.rb:278
              Array at org/jruby/RubyKernel.java:327
  target_conditions at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/query.rb:56
       source_scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:89
          query_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/relationship.rb:156
              scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/repository.rb:114
              scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/repository.rb:113
          query_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/relationship.rb:153
       resource_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:107
          lazy_load at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:191
          lazy_load at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/resource/persistence_state/persisted.rb:23
                get at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/resource/persistence_state/persisted.rb:8
          user_name at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/model/relationship.rb:351
             to_ary at /vault/1/code/ronin/ronin/lib/ronin/email_address.rb:278
              Array at org/jruby/RubyKernel.java:327
  target_conditions at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/query.rb:56
       source_scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:89
          query_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/relationship.rb:156
              scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/repository.rb:114
              scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/repository.rb:113
          query_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/relationship.rb:153
       resource_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:107
          lazy_load at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:191
          lazy_load at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/resource/persistence_state/persisted.rb:23
                get at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/resource/persistence_state/persisted.rb:8
          user_name at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/model/relationship.rb:351
             to_ary at /vault/1/code/ronin/ronin/lib/ronin/email_address.rb:278
              Array at org/jruby/RubyKernel.java:327
  target_conditions at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/query.rb:56
       source_scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:89
          query_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/relationship.rb:156
              scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/repository.rb:114
              scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/repository.rb:113
          query_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/relationship.rb:153
       resource_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:107
          lazy_load at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:191
          lazy_load at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/resource/persistence_state/persisted.rb:23
                get at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/resource/persistence_state/persisted.rb:8
          user_name at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/model/relationship.rb:351
             to_ary at /vault/1/code/ronin/ronin/lib/ronin/email_address.rb:278
              Array at org/jruby/RubyKernel.java:327
  target_conditions at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/query.rb:56
       source_scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:89
          query_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/relationship.rb:156
              scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/repository.rb:114
              scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/repository.rb:113
          query_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/relationship.rb:153
       resource_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:107
          lazy_load at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:191
          lazy_load at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/resource/persistence_state/persisted.rb:23
                get at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/resource/persistence_state/persisted.rb:8
          user_name at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/model/relationship.rb:351
             to_ary at /vault/1/code/ronin/ronin/lib/ronin/email_address.rb:278
              Array at org/jruby/RubyKernel.java:327
  target_conditions at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/query.rb:56
       source_scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:89
          query_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/relationship.rb:156
              scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/repository.rb:114
              scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/repository.rb:113
          query_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/relationship.rb:153
       resource_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:107
          lazy_load at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:191
          lazy_load at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/resource/persistence_state/persisted.rb:23
                get at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/resource/persistence_state/persisted.rb:8
          user_name at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/model/relationship.rb:351
             to_ary at /vault/1/code/ronin/ronin/lib/ronin/email_address.rb:278
              Array at org/jruby/RubyKernel.java:327
  target_conditions at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/query.rb:56
       source_scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:89
          query_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/relationship.rb:156
              scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/repository.rb:114
              scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/repository.rb:113
          query_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/relationship.rb:153
       resource_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:107
          lazy_load at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:191
          lazy_load at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/resource/persistence_state/persisted.rb:23
                get at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/resource/persistence_state/persisted.rb:8
          user_name at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/model/relationship.rb:351
             to_ary at /vault/1/code/ronin/ronin/lib/ronin/email_address.rb:278
              Array at org/jruby/RubyKernel.java:327
  target_conditions at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/query.rb:56
       source_scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:89
          query_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/relationship.rb:156
              scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/repository.rb:114
              scope at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/repository.rb:113
          query_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/relationship.rb:153
       resource_for at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:107
          lazy_load at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:191
          lazy_load at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/resource/persistence_state/persisted.rb:23
                get at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/resource/persistence_state/persisted.rb:8
          user_name at /home/hal/.rvm/gems/jruby-1.6.6/gems/dm-core-1.2.0/lib/dm-core/model/relationship.rb:351

It appears dm-core is trying to coerce the resources by calling Array() (dm-core-1.2.0/lib/dm-core/query.rb:56), which ends up calling EmailAddress#to_ary. Commenting out EmailAddress#to_ary seems to fix this. Is it possible for dm-core to avoid using Array() so I can keep the #to_ary methods, or should I remove the #to_ary methods to kill the bug?

@dkubb
Copy link

dkubb commented Mar 28, 2012

I'm not sure. I believe the purpose of a #to_ary method is that you're saying "the return value is an Array. It supports the full Array interface and can be substituted anywhere an Array is".

Is that the case with EmailAddress, is it a homogeneous list of same-typed objects? I doubt that's the case based on the name, but I'm not familiar with ronin's internals.

@postmodern
Copy link
Member Author

@dkubb So I was defining #to_ary methods on Models to allow implicit arg splatting. The EmailAddress#to_ary method simply returns an Array containing self.user_name.name and self.host_name.name, to allow this:

user, host = email

Most users probably do not know of these methods, and they are probably too subtle/clever for their own good (thus this bug). :)

@dkubb
Copy link

dkubb commented Mar 28, 2012

Yeah, I would likely reserve #to_ary for Array/Collection-like objects. Other libraries may make assumptions about objects that respond to #to_ary that could result in similar weird bugs so I'd probably recommend against it in this case.

@postmodern
Copy link
Member Author

I'm now considering removing the #to_ary methods in 1.5.0 or even 1.4.1, depending on the user feedback.

@jfredett how quickly do you need a fix for this issue?

@jfredett
Copy link

@postmodern Not quickly at all, I managed to improvise around the problem (the usage was ephemeral/proof of concept anyway) -- but this is awesome.

postmodern added a commit that referenced this issue Apr 1, 2012
* DataMapper uses Array() to coerce resources into an Array. Array()
  calls `to_ary` then `to_a`.
@postmodern
Copy link
Member Author

Ronin 1.4.1 has been released and includes the above fix. Everything should work as expected. :)

gem update ronin

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Bug Report datamapper DataMapper (legacy) model
Projects
None yet
Development

No branches or pull requests

4 participants