Ordering by a field in a join model with DataMapper
The public interface for datamapper 1.0.3 does not support ordering by a column in a joined model on a query. The core of datamapper does support this though, so we can use some hacks to make it work, as the following code demonstrates.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
require 'rubygems' require 'dm-core' require 'dm-migrations' DataMapper::Logger.new($stdout, :debug) DataMapper.setup(:default, 'postgres://localhost/test') # createdb test class User include DataMapper::Resource property :id, Serial has 1, :user_profile def self.ranked order = DataMapper::Query::Direction.new(user_profile.ranking, :desc) query = all.query # Access a blank query object for us to manipulate query.instance_variable_set("@order", [order]) # Force the user_profile model to be joined into the query query.instance_variable_set("@links", [relationships['user_profile'].inverse]) all(query) # Create a new collection with the modified query end end class UserProfile include DataMapper::Resource property :user_id, Integer, :key => true property :ranking, Integer, :default => 0 belongs_to :user end DataMapper.finalize DataMapper.auto_migrate! User.create(:user_profile => UserProfile.new(:ranking => 2)) User.create(:user_profile => UserProfile.new(:ranking => 5)) User.create(:user_profile => UserProfile.new(:ranking => 3)) puts User.ranked.map {|x| x.user_profile.ranking }.inspect |