Как вы заказываете пользовательский метод модели, который не имеет атрибута в SQL?
Ранее я заказал свои сообщения следующим образом:
@posts = Post.find(:all, :order => "created_at DESC")
Но теперь я хочу заменить created_at
на собственный метод, который я написал в модели Post, который дает номер в качестве результата.
Мое предположение:
@posts = Post.find(:all, :order => "custom_method DESC")
, который терпит неудачу.
Ответы
Ответ 1
Он терпит неудачу, потому что вы просите свой db выполнить сортировку.
@posts = Post.all.sort {|a,b| a.custom_method <=> b.custom_method}
Обратите внимание, что это становится нетривиальным, если вы хотите запустить результаты поискового вызова и больше не хотите получать .all
. Подумайте о своем дизайне немного, прежде чем идти с этим.
Ответ 2
Просто для продолжения ответа @Robbie
Post.all.sort_by {|post| post.custom_method }.reverse
Ответ 3
Как отмечалось в первом ответе, порядок - это команда Active Record, которая по сути делает SQL-запрос в вашей базе данных, но это поле фактически не существует в вашей базе данных.
Как кто-то еще прокомментировал, вы можете более чисто запустить метод Ruby sort_by, используя амперсанд (подробнее здесь):
Post.all.sort_by(&:custom_method)
Однако все усложняется в зависимости от того, что вы хотите сделать в своем представлении. Я поделюсь случаем, который недавно я сделал, в случае, если вы поможете решить свою проблему. Мне нужно было сгруппировать мой ресурс другим ресурсом под названием "категории", а затем отсортировать исходный ресурс с помощью "netvotes", который был методом пользовательской модели, а затем упорядочить по имени. Я сделал это:
- Заказ по имени в контроллере:
@resources = Resource.order(:name)
- Группировка по категориям во внешнем цикле представления:
<% @resources.group_by(&:category).each do |category, resources| %>
- Затем сортировка ресурсов по голосам в частичном для ресурсов:
<%= render resources.sort_by(&:netvotes).reverse %>
Вид немного запутан, так что вот полный цикл представления в index.html.erb:
<% @resources.group_by(&:category).each do |category, resources| %>
<div class="well">
<h3 class="brand-text"><%= category.name %></h3>
<%= render resources.sort_by(&:netvotes).reverse %>
</div>
<% end %>
И вот частица _resource.html.erb:
<div class="row resource">
<div class="col-sm-2 text-center">
<div class="vote-box">
<%= link_to fa_icon('chevron-up lg'), upvote_resource_path(resource), method: :put %><br>
<%= resource.netvotes %><br>
<%= link_to fa_icon('chevron-down lg'), downvote_resource_path(resource), method: :put %>
</div>
</div>
<div class="col-sm-10">
<%= link_to resource.name, resource.link, target: "_blank" %>
<p><%= resource.notes %></p>
</div>
</div>
Ответ 4
Ну, просто Post.find(:all)
вернет массив AR-объектов. Таким образом, вы можете использовать Array.sort_by и передать ему блок, и поскольку эти записи уже получены, вы можете получить доступ к виртуальному атрибуту внутри блока, который занимает sort_by.
RDoc: Enumerable.sort_by
Ответ 5
Это немного сложнее, чем то, что мне нравится, но это мне нравится держать мой вид, чтобы оставаться активной моделью записи, поэтому ее бит более сложный, чем просто
Post.all.sort_by {|post| post.custom_method }
что я делаю:
ids = Post.all.sort_by {|post| post.custom_method }.map(&:ids)
Post.for_ids_with_order(ids)
это настраиваемая область в модели Post
#app/models/post.rb
class Post < ApplicationRecord
...
scope :for_ids_with_order, ->(ids) {
order = sanitize_sql_array(
["position(id::text in ?)", ids.join(',')]
)
where(:id => ids).order(order)
}
...
end
Я надеюсь, что эта помощь
Ответ 6
в рельсах 3 мы можем сделать это как: Post.order("custom_method DESC")
При обновлении приложения от rails2 до rails3