Încerc să mă gândesc la o modalitate mai bună de a scrie aceste rute în fișierul routes.rb:
Rails.application.routes.draw do
root 'home#index'
s = /section1|section2|section3|section4/
y = /d{4}/
m = /d{1,2}/
resources :articles, except: [:index, :show]
# The slug will replace the default params[:id] of the following resources:
resources :articles, only: [:index, :show], path: '/:section/:year/:month', as: :my_articles, constraints: {:section => s, :year => y, month: m}
get ':section/:year/:month', to: 'articles#by_month', as: :month, constraints: {section: s, year: y, month: m}
get ':section/:year', to: 'articles#by_year', as: :year, constraints: {section: s, year: y}
get ':section', to: 'articles#by_section', as: :section, constraints: {section: s}
end
Asta îmi permite să caut articole după secțiune, după an+secțiune, după lună+secțiune+an. De asemenea, îmi permite să adaug un slug frumos la URL-uri.
Una dintre probleme este că constrângerile sunt comune tuturor acestor rute. Mă întreb dacă există o modalitate mai inteligentă de a scrie acest lucru. Cineva mi-a sugerat să folosesc preocupări, dar nu am găsit o modalitate de a face asta.
Nu este un schimbător de joc, dar sunt curios cum pot să scriu acest lucru corect.
Am înțeles:
Rails.application.routes.draw do
root 'home#index'
resources :articles, except: [:index, :show]
constraints section: /section1|section2|section3|section4/ do
constraints year: /d{4}/ do
constraints month: /d{1,2}/ do
resources :articles, only: [:index, :show], path: '/:section/:year/:month', as: :my_articles
get ':section/:year/:month', to: 'articles#by_month', as: :month
end
get ':section/:year', to: 'articles#by_year', as: :year
end
get ':section', to: 'articles#by_section', as: :section
end
Simt că este mult mai curat 🙂
Eu nu aș folosi constrângeri de rute deloc aici și aș păstra restful controller pentru simplitate și întreținere ușoară.
class ArticlesController < ApplicationController
def index
@articles = Article.by_section(params[:section])
.by_year(params[:year])
.by_month(params[:month])
end
end
apoi definiți domenii de aplicare în model pentru a permite parametrii lipsă:
class Article < AR::Base
scope :by_section, ->(section) { section.present? ? where(section: section) : all }
scope :by_year, ->(year) { year.present? ? where(year: year) : all }
scope :by_month, ->(month) { month.present? ? where(month: month) : all }
end
să se ocupe prin intermediul unei singure rute:
get '/:section(/:year(/:month))', to: 'articles#index'
și în cele din urmă în vizualizări ai putea face:
<%= link_to 'In section 1', articles_path(section: 1) %>
<%= link_to 'In section 1 in 2014', articles_path(section: 1, year: 2014) %>
Poate doriți să gestionați cazurile în care utilizatorul manipulează URL-ul și, de exemplu, pune un șir de caractere în loc de an – probabil că va rezulta o eroare din baza de date.
Personal, cred că este perfect corect să pedepsiți utilizatorii care manipulează manual URL-urile cu o pagină de eroare (500). Utilizând constrângeri ar da eroare oricum, dar cu 404 în schimb.
Dacă simțiți că trebuie să vă asigurați că utilizatorului i se permite, de exemplu, să vizualizeze doar articolele din secțiunile selectate, puteți adăuga un alt domeniu de aplicare:
scope :in_allowed_sections, -> { where(section: ['section 1', 'section 2']}
În cazul în care un utilizator rău intenționat manipulează manual URL-ul, acest lucru ar duce la o interogare SQL validă:
where section in ('section 1', 'section 2') and section = 'section 3'
iar utilizatorul va primi o pagină corectă (200), dar fără a afișa niciun articol.
- Am încercat această metodă și s-a dovedit a fi la fel de complexă ca și prima metodă. Mulțumesc totuși pentru sugestie!- > Por DaniG2k.