2009-07-14 4 views
40

У меня есть две модели в отношениях has_many, так что Log has_many Items. Затем Rails прекрасно настраивает такие вещи, как: some_log.items, который возвращает все связанные элементы в some_log. Если бы я хотел, чтобы заказать эти элементы на основе другого поля в модели Items есть способ сделать это с помощью аналогичной конструкции, или же нужно разбить на что-то вроде:Рельсы упорядочены по связанной модели

Item.find_by_log_id(:all,some_log.id => "some_col DESC") 

ответ

74

Есть несколько способов сделать это:

Если вы хотите, чтобы все вызовы в этой ассоциации заказываются таким образом, вы можете указать порядок при создании ассоциации, следующим образом:

class Log < ActiveRecord::Base 
    has_many :items, :order => "some_col DESC" 
end 

вы также можете сделать это с named_scope, что позволило бы упорядочить asily указано в любое время Пункт доступен:

class Item < ActiveRecord::Base 
    named_scope :ordered, :order => "some_col DESC" 
end 

class Log < ActiveRecord::Base 
    has_many :items 
end 

log.items # uses the default ordering 
log.items.ordered # uses the "some_col DESC" ordering 

Если вы всегда хотите детали заказываются таким же образом, по умолчанию, вы можете использовать (новый в Rails 2.3) методом default_scope следующим образом:

class Item < ActiveRecord::Base 
    default_scope :order => "some_col DESC" 
end 
+12

Так как Rails 3.x, синтаксис named_scope несколько отличается. Теперь он называется «scope» вместо «named_scope» и использует функции для определения структуры области. Например: «scope: order, order (« some_col DESC »)». –

+11

В Rails 4 снова есть другой подход. Объяснение ассоциации по умолчанию должно быть указано как лямбда, например 'has_many: items, -> {order (: some_col) .where (foo: 'bar')}' и, аналогично, области с именами теперь занимают область лямбда: name_of_scope, -> {где (foo: 'bar')} '. Область по умолчанию принимает блок: 'default_scope: {где (foo: 'bar')}' – Leo

+0

Превосходный ответ. +1 – sscirrus

4

Любой из них должен работать:

Item.all(:conditions => {:log_id => some_log.id}, :order => "some_col DESC") 
some_log.items.all(:order => "some_col DESC") 
3

набор default_scope в вашей модели класса

class Item < ActiveRecord::Base 
    default_scope :order => "some_col DESC" 
end 

Это будет работать

+2

не работает с рельсами 4 – SsouLlesS

+2

@SsouLlesS Это ответила в 2011 году, когда не было Rails 4. – Sayuj

16

рельсы 4.2.20 синтаксис требует вызова с блоком:

class Item < ActiveRecord::Base 
    default_scope { order('some_col DESC') } 
end 

Это также может быть написана с альтернативным синтаксисом:

default_scope { order(some_col: :desc) } 
Смежные вопросы