Mongoid order_by boolean

1.6k Views Asked by At

I have a notifications table in my database which contains the attributes: timestamp:datetime and read:boolean. What I want is to query and order my notifications; first by if they are read or not, then after which timestamp they've got, then limit the amount of notifications to 10.

The query I've tried looks something like this:

@user.notifications.order_by([[:read,:desc],[:timestamp,:desc]]).limit(10)

Which only gives me an error which I narrowed down to proving the boolean field as the culprit.

Is there an existing way of ordering by true/false values or should I resort to using some kind of Custom Field Serialization transforming True's and False's to 1's and 0's?

1

There are 1 best solutions below

1
Gary Murakami On BEST ANSWER

What you specify works for me with Mongoid 2.4.10, mongo 1.3, rails 3.2.3. Hope that the following helps to address your problem.

class User
  include Mongoid::Document

  field :name, type: String
  has_many :notifications
end

class Notification
  include Mongoid::Document

  field :read, type: Boolean
  field :timestamp, type: DateTime
  belongs_to :user
end

test/unit/notification_test.rb

require 'test_helper'

class NotificationTest < ActiveSupport::TestCase
  def setup
    User.delete_all
    Notification.delete_all
  end

  test "order_by boolean" do
    @user = User.create(name: 'Gary')
    [
      [true, 1.day.ago], [false, 2.days.ago], [false, 3.days.ago], [true, 5.days.ago], [false, 8.days.ago], [true, 11.days.ago],
      [false, 4.days.ago], [true, 6.days.ago], [true, 7.days.ago], [false, 9.days.ago], [false, 10.days.ago]
    ].each do |read, timestamp|
      @user.notifications << Notification.create(read: read, timestamp: timestamp)
    end
    assert_equal(1, User.count)
    assert_equal(11, Notification.count)
    result = @user.notifications.order_by([[:read,:desc],[:timestamp,:desc]]).limit(10).to_a
    assert_equal(10, result.size)
    result.each do |r|
      p [r.read, r.timestamp]
    end
  end
end

test output

Run options: --name=test_order_by_boolean

# Running tests:

[true, Mon, 28 May 2012 12:33:49 -0400]
[true, Thu, 24 May 2012 12:33:49 -0400]
[true, Wed, 23 May 2012 12:33:49 -0400]
[true, Tue, 22 May 2012 12:33:49 -0400]
[true, Fri, 18 May 2012 12:33:49 -0400]
[false, Sun, 27 May 2012 12:33:49 -0400]
[false, Sat, 26 May 2012 12:33:49 -0400]
[false, Fri, 25 May 2012 12:33:49 -0400]
[false, Mon, 21 May 2012 12:33:49 -0400]
[false, Sun, 20 May 2012 12:33:49 -0400]
.

Finished tests in 0.023062s, 43.3614 tests/s, 130.0841 assertions/s.

1 tests, 3 assertions, 0 failures, 0 errors, 0 skips