identity map, includes and sorting

71 views
Skip to first unread message

Craig White

unread,
Apr 9, 2012, 7:33:53 PM4/9/12
to mon...@googlegroups.com
I can't seem to make it work.

Simplified...

class Right
include Mongoid::Document
field :controller, :type => String
field :action, :type => String

belongs_to :role
end

class Role
include Mongoid::Document
include Mongoid::Timestamps

field :name , :type => String
has_many :rights
index :name, :unique => true
end

config/mongoid.yml
development:
host: localhost
database: tti_framework_development
identity_map_enabled: true

and then in the console, I'm trying to get a list of 'Rights' sorted by the associated 'Role' name

irb(main):035:0> rights = Right.all(:sort => 'role.name').includes(:roles)
=> #<Mongoid::Criteria
selector: {},
options: {:sort=>"role.name"},
class: Right,
embedded: false>

irb(main):036:0> rights.size
=> 175
irb(main):037:0> rights.each do |ri|
irb(main):038:1* p ri.role.name
irb(main):039:1> end
"Permissions Admin"
..snip...

Which of course cannot be the first Role name in the sorted list

obviously something basic is escaping me

--
Craig White ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ craig...@ttiltd.com
1.800.869.6908 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ www.ttiassessments.com

Need help communicating between generations at work to achieve your desired success? Let us help!

Durran Jordan

unread,
Apr 10, 2012, 2:32:45 AM4/10/12
to mon...@googlegroups.com
The sort option is incorrect - I'm actually surprises the ruby driver didn't raise an error for that. You want:

Right.asc("role.name").includes(:roles)

2012/4/10 Craig White <craig...@ttiltd.com>

Craig White

unread,
Apr 10, 2012, 11:33:09 AM4/10/12
to mon...@googlegroups.com
Seems that the ruby driver is fairly tolerant of much of my abuse but alas...

rights = Right.asc("role.name").includes(:roles)

still gives me an 'unsorted' list.

irb(main):045:0> rights = Right.asc("role.name").includes(:roles)


=> #<Mongoid::Criteria
selector: {},

options: {:sort=>[["role.name", :asc]]},
class: Right,
embedded: false>

irb(main):046:0> rights.each do |ri|
irb(main):047:1* p ri.role.name
irb(main):048:1> end
"Permissions Admin"
"Permissions Create"
... snip...

Craig

kuadrosx (Jorge Cuadrado)

unread,
Apr 10, 2012, 12:31:05 PM4/10/12
to mon...@googlegroups.com
Sorting by a "foreign key" field is not possible in mongodb because mongodb does not have joins.

you can change your schema design to use embedded relationships http://mongoid.org/docs/relations/embedded.html 
embedding rigths in role, but that will change the behavior of Roles not allowing make queryins use Role model.


Craig White

unread,
Apr 10, 2012, 2:07:30 PM4/10/12
to mon...@googlegroups.com

----
I sort of need Right class on its own and not embedded for other purposes but I thought that was the point of MongoID associations and identity_map but apparently not.

For now, I am sorting manually (Right.all.sort{|a,b| a.role.name <=> b.role.name}) and then had to make an adjustment (a new will_paginate_array_helper module) to allow will_paginate to paginate the array but it is working.

Thanks

Craig

kuadrosx (Jorge Cuadrado)

unread,
Apr 10, 2012, 2:56:24 PM4/10/12
to mon...@googlegroups.com
Another solution(and better) is copy the role name into the role and using callbacks and atomic update to keep it updated.

Alexey Savartsov

unread,
Apr 10, 2012, 3:07:58 PM4/10/12
to mon...@googlegroups.com
There is also mongoid_denormalize gem which I'm widely using for that.

-- Alexey

Reply all
Reply to author
Forward
0 new messages