2009-07-13 5 views
0

J'ai une configuration RESTful pour les routes dans une application Rails en utilisant des permaliens de texte comme ID pour les ressources.Valider aucun chevauchement de routage lors de la création de nouvelles ressources dans Ruby on Rails

En outre, il y a quelques itinéraires spéciaux nommés et qui se chevauchent avec la ressource nommée par exemple:

# bunch of special URLs for one off views to be exposed, not RESTful 
map.connect '/products/specials', :controller => 'products', :action => 'specials' 
map.connect '/products/new-in-stock', :controller => 'products', :action => 'new_in_stock' 

# the real resource where the products are exposed at 
map.resources :products 

Le modèle Product est d'utiliser permalink_fu pour générer permaliens en fonction du nom, et ProductsController fait une recherche sur le champ permalien lors de l'accès. Tout fonctionne bien.

Cependant lors de la création de nouveaux Product enregistrements dans la base de données, je veux valider que le permalien généré ne pas chevauchement avec une URL spéciale.

Si un utilisateur essaie de créer un produit nommé specials ou new-in-stock ou même un Rails normaux méthode de ressources RESTful comme new ou edit, je veux que le contrôleur lookup la configuration de routage, définissez des erreurs sur l'objet modèle, validation échoue pour la nouvel enregistrement, et ne pas l'enregistrer.

Je pourrais coder en dur une liste de noms permaliens illégaux connus, mais cela semble désordonné de le faire de cette façon. Je préférerais me connecter au routage pour le faire automatiquement.

(noms de contrôleur et le modèle a changé pour protéger les innocents et de le rendre plus facile de répondre, la configuration réelle est plus complexe que cet exemple)

Répondre

1

Eh bien, cela fonctionne, mais je ne sais pas comment elle est jolie . Le principal problème est de mélanger la logique de contrôleur/routage dans le modèle. Fondamentalement, vous pouvez ajouter une validation personnalisée sur le modèle pour le vérifier. C'est en utilisant des méthodes de routage non documentées, donc je ne suis pas sûr de la stabilité à venir. Quelqu'un a de meilleures idées?

class Product < ActiveRecord::Base 
    #... other logic and stuff here... 

    validate :generated_permalink_is_not_reserved 

    def generated_permalink_is_not_reserved 
    create_unique_permalink # permalink_fu method to set up permalink 
    #TODO feels really ugly having controller/routing logic in the model. Maybe extract this out and inject it somehow so the model doesn't depend on routing 
    unless ActionController::Routing::Routes.recognize_path("/products/#{permalink}", :method => :get) == {:controller => 'products', :id => permalink, :action => 'show'} 
     errors.add(:name, "is reserved") 
    end 
    end 
end 
+0

Cela semble être le chemin à suivre, mais je ne m'inquiéterais pas d'avoir une logique de routage/contrôleur dans le modèle et d'essayer de le séparer. Le fait est que dans votre système, le modèle * dépend * du routage - ce n'est tout simplement pas un modèle valide s'il se heurte à une autre route. – ideasasylum

0

Vous pouvez utiliser une route qui n'existerait pas autrement. De cette façon, cela ne fera aucune différence si quelqu'un choisit un mot réservé pour un titre ou non.

map.product_view '/product_view/:permalink', :controller => 'products', :action => 'view' 

Et dans votre point de vue:

product_view_path(:permalink => @product.permalink) 
+0

Malheureusement, ce n'est pas une option dans ce cas. Les URL sont déjà configurées et ont une valeur SEO liée, ainsi que d'autres configurations de système qui en dépendent, etc., elles ne peuvent donc pas être changées facilement. Tout fonctionne comme il est, c'est juste que si un utilisateur crée un nom qui se chevauche, ce produit est ignoré efficacement par le système. – madlep

+0

Vous pouvez également prendre une page sur les exemples typiques de "to_param" et ajouter l'ID au nom. Vous vous retrouvez avec des liens permanents qui ressemblent à "01-foo-bar". – jdl

0

Il est une meilleure pratique de gérer vous-même explicitement URIs pour des raisons comme celle-ci, et pour éviter d'exposer accidentellement les routes que vous ne voulez pas.