2010-02-05 9 views
51

Teniendo en cuenta los siguientes modelos AR, quisiera ordenar los usuarios alfabéticamente por el apellido cuando se le da un identificador para una tarea:¿Cómo pido una asociación de has_many a través de Ruby on Rails?

me gustaría obtener una tarea, entonces, la navegación a sus usuarios asignados, y clasificar la lista de usuarios alfabéticamente.

sigo pensando que debería ser capaz de añadir la cláusula :order a has_many :users, :through => :assignments así:

#task.rb 
has_many :assignments 
has_many :users, :through => :assignments, :order => 'last_name, first_name' 

sin embargo, esto no funciona.

¿Cómo puedo ordenar a los usuarios por last_name cuando se les asigna una tarea?

Respuesta

7

¿Funcionaría para usted?

# User.rb 

class User < ActiveRecord::Base 
default_scope :order => 'last_name ASC' 
... 
end 

Puede definir otros ámbitos nombrados para cuando la ordenación tenga que ser diferente.

http://ryandaigle.com/articles/2008/11/18/what-s-new-in-edge-rails-default-scoping

+2

Lamento responder a una pregunta anterior, pero podría ser relevante para futuros lectores: algunos complementos (act_as_list por ejemplo) no funcionan correctamente con default_scope. – robinjam

+0

También chocando esto porque tenía un problema similar, pero necesitaba ordenar en un campo EN: a través de la tabla: lo asombroso es que default_scope también funciona en la tabla: y los registros recuperados a través de esa relación respetarán el orden. – MBHNYC

36

rieles versión 3.x:

has_many :users, :through => :assignments, :order => 'users.last_name, users.first_name' 

ACTUALIZACIÓN: Esto sólo funciona en los carriles 3.x (tal vez antes de eso también). Para 4+, vea otras respuestas.

+0

Funciona bien para mí también. Solución limpia que no afecta otras funciones del modelo ordenado como lo hace la primera respuesta. – barancw

+2

no funciona, dice: el orden no es una clave. La respuesta a continuación de Denial IS está funcionando. – RohitPorwal

12

El enfoque M.G.Palmer's funciona bien, sin importar el nombre de la tabla. Hay una mejor manera de hacerlo:

has_many :users, :through => :assignments, :order => [ :last_name, :first_name ] 
+0

, pero ¿qué ocurre si la orden se determina mediante la tabla de unión? p.ej. asignaciones ... pero sin definir un alcance predeterminado en las asignaciones. – Tilo

2

También puede crear una nueva columna 'sort_order' en la tabla de asignación, y añadir un ámbito predeterminado como

default_scope { order('sort_order desc')} 

a su modelo de asignaciones.

65

Desde argumentos de la condición están en desuso en los carriles 4, se debe utilizar bloques de alcance:

has_many :users, -> { order 'users.last_name, users.first_name' }, :through => :assignments 
+1

Parece que actualmente hay un error en Rails 4 con este https://github.com/rails/rails/issues/17904 "En Rails 4.0, el La cláusula order fue ignorada. En Rails 4.1, se genera SQL no válido. – Nate

+0

Ni siquiera me da eso, simplemente ignora por completo la cláusula de pedido sin mensaje. –

6

Esto funciona para mí (carriles 4,2)

La aplicación de un ordenamiento en el medio del mapa no se conserva, también conocido como esto no es suficiente para tener los géneros ordenó:

has_many :disk_genre_maps, 
      -> {order('disk_genre_map.sort_order')}, 
      :inverse_of => :disk, 
      :dependent => :destroy, 
      :autosave => true 


has_many :genres, # not sorted like disk_genre_maps 
      :through => :disk_genre_maps, 
      :source  => :genre, 
      :autosave => true 

Así que sobreescriben por ejemplo:

def genres # redefine genres per instance so that the ordering is preserved 
    self.disk_genre_maps.map{|dgm|dgm.genre} 
end 

Para hacer que el trabajo para las asignaciones, esto debería ser algo como esto (no probado)

def genres= some_genres 
    self.disk_genre_maps = some_genres.map.with_index do |genre, index| 
     DiskGenreMap.new(disk:self, genre:genre, sort_order:index) 
    end 
end 
2

estoy usando carriles (5.0.0.1) y podría hacer que el género con esta sintaxis en mi modelo de grupo que tiene muchos usuarios a través de grupos_usuarios:

# Associations. 
has_many :group_users 
has_many :users, -> { order(:name) }, through: :group_users 

Ajuste el código a su necesidad que funcionará.

Cuestiones relacionadas