0

I'm using Rails 5 with Ransack, and I have a Model with a column in my Mysql db called status. Status is an integer from 0-5. I am trying to create a default ordering on this column where it is ascending, with the exception of status's that are 0 being last (1, 2, 3, 4, 5, 0).

I am able to get the objects in ascending order without the objects where status == 0 with:

  scope :asc_no_approved, lambda { where.not(status: [0]).order('status ASC') }

And the objects where status == 0 with:

  scope :approved, lambda { where(status: [0]) }

Is there a way to append this second scope to the end of the first? I tried:

scope :asc_approved_last, lambda { where.not(status: [0]).order('status ASC').where(status: [0]) }

But that returns no objects with the following Mysql:

SELECT  `requests`.* FROM `requests` WHERE (`requests`.`status` != 0) AND `requests`.`status` = 0 ORDER BY status ASC LIMIT 10 OFFSET 0

UPDATE:

Since the comments below are somewhat confusing, if anyone else is trying to solve this, this is what worked for me. As per the accepted answer, these are my scopes:

scope :asc_no_approved, lambda { where.not(status: [0]).order('status ASC') }
scope :approved, lambda { where(status: [0]) }
scope :asc_approved_last, lambda { asc_no_approved + approved }

And here is my call in the controller:

@requests = Kaminari.paginate_array(@q.result.includes(:employee, :user, :title).asc_approved_last).limit(10).page(params[:page])
cm1745
  • 120
  • 2
  • 12

1 Answers1

2

You can chain scopes together like that fine, you could even just do asc_no_approved.approved but I think the reason it is returning zero objects is because you are looking for all things where the status is not 0, and then asking for the things of this collection where the status is 0.

WHERE (`requests`.`status` != 0) AND `requests`.`status` = 0

If you want to literally append the results of approved to asc_no_approved then you could just do approved + asc_no_approved

Tom Finney
  • 2,670
  • 18
  • 12
  • That makes sense, thanks! Since I have them in scopes would it be best to do `approved + asc_no_approved` in a method? – cm1745 Jul 07 '17 at 16:29
  • I'm not really the best on code style but a scope is essentially a class method so you could have another scope that is adding the two collections together or just have a class method that does the same thing. I would probably just go for the scope to keep things clearer? – Tom Finney Jul 10 '17 at 14:40
  • If I chain them together like so: `scope :asc_approved_last, lambda { asc_no_approved.approved }` I get the same MySQL call where it returns 0 objects, and if I try adding them like so: `scope :asc_approved_last, lambda { asc_no_approved + approved }` I get this error with my pagination: `undefined method `page' for #`. Not sure why it isn't letting me use the pagination. If I use just one of the scopes it still works. – cm1745 Jul 10 '17 at 14:54
  • I just took out the pagination though and it does correctly sort. Now I just need to figure out how to use it with pagination (Kaminari). – cm1745 Jul 10 '17 at 14:56
  • Fixed it by using `@requests = Kaminari.paginate_array(@q.result.includes(:employee, :user, :title).asc_approved_last).limit(10).page(params[:page])`. Found at: https://stackoverflow.com/questions/21464324/kaminari-undefined-method-page. Thanks for your help! Marking as solved. – cm1745 Jul 10 '17 at 15:06