Empty DataMapper::Collection returns everything on chaining. Bug?

60 views
Skip to first unread message

Michael Kebbekus

unread,
Apr 19, 2011, 7:11:20 PM4/19/11
to DataMapper
class Membership
include DataMapper::Resource

property :id, Serial
property :project_id, Integer
property :user_id, Integer

belongs_to :user
belongs_to :project
end

>> Membership.all(:project_id => [])
=> []
>> Membership.all(:project_id => []).class
=> DataMapper::Collection
>> Membership.all(:project_id => []).user
=> [#<User @id=1 @created_at=Tue Apr 19 21:31:54 UTC 2011
@updated_at=Tue Apr 19 21:31:54 UTC 2011 @full_name="Andy Goodell"
@hashed_password=<not loaded> @salt="HQG8wpuoa5" @active=true
@primary_email_id=1 @provenance="signup" @legitimized_at=nil
@entry_credentials="google" @admin=<not loaded>
@calendar_synced_setting=false @google_calendar_id_setting=nil
@nag_setting=<not loaded> @last_nagged_setting=<not loaded>
@newsletter_setting=<not loaded> @messaging_level_setting=1
@settings_converted=false @picture_file_name=nil
@picture_content_type=<not loaded> @picture_file_size=<not loaded>
@picture_updated_at=nil @editable_picture_file_name=nil
@editable_picture_content_type=<not loaded>
@editable_picture_file_size=<not loaded>
@editable_picture_updated_at=nil>]

Isn't this supposed to be a more efficient way of saying
Membership.all(:project_id => []).map(&:user) which returns []?

As far as why I'm searching for :project_id => [], this is a
simplified version of the real code. We calculate the list of project
ids we're interested in, but some users of our site are not on any
projects.

Piotr Solnica

unread,
Apr 20, 2011, 3:10:18 AM4/20/11
to DataMapper
Hi Michael

On Apr 20, 1:11 am, Michael Kebbekus <makebbe...@gmail.com> wrote:
> Isn't this supposed to be a more efficient way of saying
> Membership.all(:project_id => []).map(&:user) which returns []?

Yes it is. I don't know how your relationships are set up exactly, but
the following example works for me:

class Project
include DataMapper::Resource

property :id, Serial

has n, :memberships
has n, :users, :through => :memberships
end

class Membership
include DataMapper::Resource

belongs_to :project, :key => true
belongs_to :user, :key => true
end

class User
include DataMapper::Resource

property :id, Serial

has n, :memberships
has n, :projects, :through => :memberships, :via => :project
end

DataMapper.finalize
DataMapper.auto_migrate!

project = Project.create
user = User.create

project.users << user
project.save

# you can grab users either via project:
Project.all(:id => [project.id]).users

# or membership
Membership.all(:project_id => [project.id]).user

Hope this helps

Cheers!

# solnic

Michael Kebbekus

unread,
Apr 20, 2011, 2:53:30 PM4/20/11
to DataMapper
Hey sonlic,

That looks about right as per our setup, but what happens when you do
Membership.all(:project_id => []).user with an empty array?

I'm suggesting that I've found a bug, because I get back the whole
user table even though Memberhip.all(:project_id => []) correctly
returns an empty Datamapper::Collection.

>> Membership.all(:project_id => [])
=> []
>> Membership.all(:project_id => []).class
=> DataMapper::Collection
>> Membership.all(:project_id => []).user #returns every User!?!?

RipTheJacker

unread,
Apr 28, 2011, 6:52:42 PM4/28/11
to DataMapper
This is the query that is done when you search on an empty array:

SELECT "id" FROM "users" WHERE "id" IN (SELECT "user_id" FROM
"memberships") ORDER BY "id"

That is incorrect, and a bug. You can get around this by using two
statements:

memberships = Membership.all(:project_ids => []) # => will return an
empty array, as expected
memberships.users # => will return [] or the users

It probably isn't ideal, but at least when you do
Membership.all(:project_ids => []) on an empty array, no query gets
run.

Michael Kebbekus

unread,
Apr 30, 2011, 11:27:10 AM4/30/11
to DataMapper
Thanks RipTheJacker.

That's definitely the bug I was getting at, and that workaround helps!
Reply all
Reply to author
Forward
0 new messages