Сделайте любой заказ цепочкой - PullRequest
1 голос
/ 20 февраля 2011

Я хочу отсортировать мои Person объекты модели на основе сложного критерия, который нельзя суммировать в одном запросе - и, следовательно, в именованной области. Прямо сейчас я использую метод класса как:

def Person.very_complicated_sorting
  Person.all.sort { |x,y| x.bunch_of_calculations <=> y.bunch_of_calculations }
end

Есть ли способ сделать это цепным? Э.Г.

Person.tallest.very_complicate_sorting.youngest

, где tallest и youngest - две именованные области.

Ответы [ 3 ]

1 голос
/ 20 февраля 2011

К сожалению, это невозможно.

Способ работы с именованными областями заключается в "ленивом" создании комбинированного набора параметров SQL, которые не оцениваются, пока вы на самом деле не попытаетесь что-то с ними сделать.Так, например, следующая цепочка именованных областей:

people = Person.tallest.youngest

вызовет , а не , что приведет к выполнению любого запроса к базе данных, на самом деле объект ActiveRecord::NamedScope будет сохранен в people переменная.Только когда вы обращаетесь к этому объекту или выполняете итерацию по нему, запускается SQL и загружаются объекты.

Ваша проблема в том, что ваш метод сортировки не выражается в SQL, это набор условий Ruby.Когда Rails добирается до вашего sort_by, он должен пойти и извлечь и создать экземпляры объектов Person, чтобы он мог выполнить ваши условия на них.После этого у вас будет Array объектов, а не NamedScope объектов.

0 голосов
/ 20 февраля 2011

Это возможно, если вы используете Sequel вместо ActiveRecord для вашей библиотеки базы данных.Он позволяет использовать def_dataset_method в моделях для создания методов, которые работают с наборами данных (из которых включены модели);до тех пор, пока ваши методы возвращают набор данных, вы можете связывать их по своему усмотрению.Например:

class Person < Sequel::Model
  def_dataset_method :active_only do
    filter :active=>true
  end
  def_dataset_method :sort_much do
    order :name, :age.desc
  end
end

active_peeps = Person.active_only.sort_much
peeps_active = Person.sort_much.active_only

Чтобы остаться на земле набора данных, вам нужно использовать только методы, которые могут быть выражены как SQL.Вы не можете ожидать запроса некоторых записей из базы данных, а затем выполнять сложную логику только для Ruby (скажем, сортировать их по их object_id, найденному в Ruby Hash), и затем продолжают выполнятьсяSQL на результирующий массив.Ruby не работает в вашей базе данных (кроме pl / Ruby ).

В качестве альтернативы, вы можете перейти прямо к массиву Ruby и затем связать любые методы Ruby в любом порядке, есливсе они работают с массивами и возвращают массивы.Вы должны принять четкое решение в своем коде относительно того, когда вы собираетесь получать результаты из базы данных, а затем работать с массивом.

0 голосов
/ 20 февраля 2011

Ваш very_complicated_sorting должен быть в вашей Person модели.

Вы не должны писать Person.all внутри метода, иначе он не может быть цепным.

Просто держите:

def self.very_complicated_sorting
  sort_by { |x,y| x.bunch_of_calcultaions <=> y.bunch_of_calculations }
end
...