Sort_by в Hash - обратный или не обратный - как?

У меня есть хэш, ниже:

library = {"1"=>{"title"=>"bbb", "money"=>10}, "2"=>{"title"=>"aaa", "money"=>12}}

и мой application_helper.rb:

  def sortable_columns
    %w[title money]
  end

  def sort_column
    sortable_columns.include?(params[:column]) ? params[:column] : "title"
  end

  def sort_direction
    %w[asc desc].include?(params[:direction]) ? params[:direction] : "asc"
  end

  def sort_link(column, title)
    direction = column == sort_column && sort_direction == "asc" ? "desc" : "asc"
    icon = sort_direction == "asc" ? "fa fa-arrow-down" : "fa fa-arrow-up"
    icon = column == sort_column ? icon : ""
    link_to "#{title} <i class='#{icon}'></i>".html_safe, {column: column, direction: direction}
  end

Моя таблица в table.html.erb:

          <table class="table table-striped">
            <thead>
            <tr>
                <th>#</th>
                <% sortable_columns.each do |column| %>
                  <th><%= sort_link column, column %></th>
                <% end %>
            </tr>
            </thead>
            <tbody>
              <% library.sort_by {|k| k[1][sort_column]}.each_with_index do |data, i| %>
               ...

              <% end %>
            </tbody>
          </table>

и теперь - после клика в заголовке "название" или "деньги" - сортировка таблицы ASC. Я хотел бы, чтобы он отображал DESC при повторном нажатии (со стрелкой вниз). Как это может быть сделано? Думал про "реверс" после library.sort_by {|k| k[1][sort_column]}, но не работает.


person Kamil Pikula    schedule 21.05.2019    source источник
comment
Поскольку вся библиотека отображается на стороне клиента, не рассматривали ли вы возможность использования одного из различных решений для сортировки таблиц JavaScript?   -  person Stefan    schedule 21.05.2019
comment
Нет, я не рассматривал. У вас есть идея?   -  person Kamil Pikula    schedule 21.05.2019
comment
Возможно, tablesorter? Вы также можете написать свой собственный, см. Сортировка таблицы HTML с помощью JavaScript   -  person Stefan    schedule 21.05.2019
comment
Кстати, почему вы поместили данные в хэш, а не в таблицу базы данных? Не лучше ли было бы использовать ActiveRecord, учитывая, что это вопрос о Rails?   -  person Stefan    schedule 21.05.2019
comment
@Stefan, потому что я получаю данные из API в формате json, и мне не нужно хранить их в базе данных. Ваш способ работает, но я использовал метод tap в Ruby. Спасибо. :)   -  person Kamil Pikula    schedule 22.05.2019


Ответы (2)


Обратное работает:

library = {"1"=>{"title"=>"bbb", "money"=>10}, "2"=>{"title"=>"aaa", "money"=>12}}

sort_column = "money"

sort_direction = "asc"
library
  .sort_by {|k| k[1][sort_column]}
  .tap { |l| l.reverse! if sort_direction == "desc" }
# => [["1", {"title"=>"bbb", "money"=>10}], ["2", {"title"=>"aaa", "money"=>12}]]

sort_direction = "desc"
library
  .sort_by {|k| k[1][sort_column]}
  .tap { |l| l.reverse! if sort_direction == "desc" }
# => [["2", {"title"=>"aaa", "money"=>12}], ["1", {"title"=>"bbb", "money"=>10}]]
person fphilipe    schedule 21.05.2019
comment
К сожалению, нет, library не является отношением AR, это ActiveSupport::HashWithIndifferentAccess - person Kamil Pikula; 21.05.2019
comment
@KamilPikula, что такое ключи и значения? Вы говорите, что это массив ActiveSupport::HashWithIndifferentAccess, где каждый элемент представляет собой строку, а столбец, по которому вы хотите отсортировать, является ключом в каждом хэше? - person fphilipe; 21.05.2019
comment
@KamilPikula, извините, пропустил, что в вашем вопросе было library. Обновил мой ответ соответственно. - person fphilipe; 21.05.2019
comment
Черт возьми, я совсем забыл о методе tap в Ruby. Это работает, большое спасибо @fphilipe! - person Kamil Pikula; 22.05.2019

вы можете извините хеш, как показано ниже

если сортировать только по названию то

library.values.sort_by{|h| h["title"] }

или вы хотите отсортировать по первому названию и вторым деньгам, а затем используйте

library.values.sort_by{|h| [h["title"], h["money"]] }
person NensiMakawana    schedule 21.05.2019