There is a Task model, in it the date attribute ( date data type) that the user selects when filling out the form, in the format "2016-05-28".

How to make a list ( @task.each do , etc.), in which Task objects with the closest date selected by the user would be displayed at the top (and further descending)?

    1 answer 1

    If the model is inherited from the base class ActiveRecord and supports ActiveRecord methods, you can sort the output using the order method

     @tasks = Task.order(start_at: :desc) @tasks.each do |task| ... 

    Older versions of Ruby on Rails that do not support this syntax may need to explicitly write a sort string.

     @tasks = Task.order('start_at DESC') @tasks.each do |task| ... 

    To retrieve the nearest date, you can run a query like

     SELECT id FROM tasks ORDER BY ABS(start_at - NOW()) LIMIT 1 

    Further, the received identifier of the nearest record can be used to place it first. Let id = 2

     SELECT * FROM tasks ORDER BY IF(id = 2, 0, 1), start_at DESC 

    Combining the two queries, you can get the following

     SELECT * FROM tasks ORDER BY IF(id = (SELECT id FROM tasks ORDER BY ABS(created - NOW()) LIMIT 1), 0, 1), start_at DESC 

    As a result, the nearest record will be recorded first, and after it all the other records will go. Now you can transfer the received request to ActiveRecord

     order_by = 'IF(id = (SELECT id FROM tasks ORDER BY ABS(created - NOW()) LIMIT 1), 0, 1), start_at DESC' @tasks = Task.order(order_by) @tasks.each do |task| 

    It is better, of course, to organize the scope at the model level.

     scope :ordered, -> { order_by = 'IF(id = (SELECT id FROM tasks ORDER BY ABS(created - NOW()) LIMIT 1), 0, 1), start_at DESC' order(order_by) } 

    Then it will be possible to access the model as follows.

     @tasks = Task.all.ordered @tasks.each do |task| ...