2008-10-18 4 views
9

Je suis en train d'utiliser un simple find all et pagination avec willpaginate, mais j'aimerais aussi que la requête soit triée par l'utilisateur. La première solution qui vient à l'esprit était juste utiliser un params [:] trierRails: trier une requête par params?

http://localhost:3000/posts/?sort=created_at+DESC 

@posts = Post.paginate :page => params[:page], :order => params[:sort] 

Mais le problème avec son approche est que la requête est en défaut que le tri par ID et je veux que ce soit created_at.

Est-ce une approche sûre pour le tri et existe-t-il un moyen de définir par défaut à created_at?

Répondre

15

j'utiliser un champ nommé pour fournir l'ordre par défaut (disponible depuis Rails 2.1).

Vous souhaitez ajouter la portée dans votre modèle Post:

named_scope :ordered, lambda {|*args| {:order => (args.first || 'created_at DESC')} } 

vous pouvez appeler:

@posts = Post.ordered.paginate :page => params[:page] 

L'exemple sera ci-dessus utilisent l'ordre par défaut de la named_scope (created_at DESC), mais vous pouvez également en fournir un autre:

@posts = Post.ordered('title ASC').paginate :page => params[:page] 

Vous pouvez utiliser t chapeau avec la suggestion de Romulo:

sort_params = { "by_date" => "created_at", "by_name" => "name" } 
@posts = Post.ordered(sort_params[params[:sort]]).paginate :page => params[:page] 

Si params[:sort] ne se trouve pas dans sort_params et retourne alors nilnamed_scope va revenir à l'aide de l'ordre par défaut.

Railscasts a d'excellentes informations sur named_scopes.

2

En général, la façon de fournir des valeurs par défaut pour les objets de hachage et comme Hash est d'utiliser fetch:

params.fetch(:sort){ :created_at } 

Beaucoup de gens utilisent simplement || si:

params[:sort] || :created_at 

Je préfère fetch moi-même comme étant plus explicite, plus il ne casse pas lorsque false est une valeur légitime.

1

idiome Ruby pour définir une valeur par défaut serait:

@posts = Post.paginate :page => params[:page], :order => params[:sort] || "created_at" 

Mais l'approche n'est pas sûr. La méthode paginate ne dérange pas avec un paramètre comme "created_at; DROP DATABASE mydatabase;". Au lieu de cela, vous pouvez utiliser un dictionnaire des paramètres de tri valides (non testé):

sort_params = { "by_date" => "created_at", "by_name" => "name" } 

@posts = Post.paginate :page => params[:page], :order => sort_params[params[:sort] || "by_date"] 

Alors que l'URI devient:

http://localhost:3000/posts/?sort=by_date 
1

Je préfère cet idiome:

@posts = Post.paginate :page=>page, :order=>order 
... 

def page 
    params[:page] || 1 
end 

def order 
    params[:order] || 'created_at ASC' 
end