Как сделать URL в Ruby on Rails SEO дружественным, зная @vendor.name?

Мое приложение в RoR

У меня есть action/view, называемый showummary, где идентификатор был передан в URL-адрес, а контроллер использовал это для создания @vendor, где @vendor.name - название компании.

Я хотел бы, чтобы URL-адрес был, а не showummary/1/, чтобы иметь/имя-поставщика в URL-адресе.

Как это сделать?

Ответ 1

Во всех этих решениях используется find_by_name, что, безусловно, требует наличия индекса в этом столбце и требует, чтобы они были уникальными. Лучшим решением, которое мы использовали, жертвуя небольшим количеством красоты, является использование префикса имени поставщика с его идентификатором. Это означает, что вам не нужно иметь индекс в столбце имени и/или требовать уникальности.

vendor.rb

def to_param
  normalized_name = name.gsub(' ', '-').gsub(/[^a-zA-Z0-9\_\-\.]/, '')
  "#{self.id}-#{normalized_name}"
end

Итак, это даст вам URL-адреса, например

/1-Акме

/19-Safeway

и т.д.

Затем в вашем действии show вы все равно можете использовать

Vendor.find(params[:id])

поскольку этот метод будет неявно вызывать .to_i в своем аргументе, а вызов to_i в такой строке всегда будет возвращать числовой префикс и отбрасывать оставшийся текст - все его пух в этой точке.

Вышеупомянутое предполагает, что вы используете маршрут по умолчанию /:controller/:action/:id, который сделает ваши URL-адреса похожими на

/vendors/show/1-Acme

Но если вы хотите, чтобы они просто смотрели

/1-Акме

Затем введите маршрут, например

map.show_vendor '/:id', :controller => 'vendors', :action => 'show'

Это означало бы, что он в значительной степени проглотит много URL-адресов, которые, вероятно, вам тоже не нужны. Возьмите предупреждение.

Ответ 2

Я думал, что я упомянул параметр String # parameterize, в качестве дополнения к помеченному ответу.

def to_param
  "#{id}-#{name.parameterize}"
end

Он будет отфильтровывать переносимые символы, заменять пробелы тире и т.д.

Ответ 3

Райан Бейтс имеет отличный screencast по этому самому вопросу.

В основном вы перегружаете метод to_param в модели поставщика.

   def to_param
     permalink
   end

Затем, когда вы просматриваете ресурс в своем контроллере, вы делаете что-то вроде этого:

   @vender = Vender.find_by_name(params[:id])

Но проблема заключается в том, что вам нужно убедиться, что имена поставщиков уникальны. Если они не могут быть тогда другим решением, которое предлагает Райан, где он добавляет идентификатор к имени, а затем анализирует полученный uri, чтобы найти идентификатор элемента.

Ответ 4

Вы делаете это, изменяя маршруты, которые используются для доступа к указанному URL, и изменяя их для использования: name, а не: id. Это, вероятно, означает, что вы должны сами писать маршруты, а не полагаться на ресурсы.

Например, добавьте это в файл routes.rb:

map.with_options :controller => "vendor" do |vendor|
  vendor.connect "/vendor/:name", :action => "show"
  # more routes here for update, delete, new, etc as required
end

Другим изменением, которое потребуется, является то, что теперь вам нужно будет найти объект-продавец в базе данных по имени, а не по идентификатору, поэтому:

@vendor = Vendor.find_by_name(params[:name])

Внутри (по крайней мере, до моих знаний/экспериментов) любое имя параметра не указано в URL-адресе маршрута (т.е. не в части "/Controller/Action/: id" ) прикрепляется к концу как параметр.

Ответ 6

Мне нужно немного поэкспериментировать, чтобы понять это, но есть две основные части решения.

1) Добавьте маршрут. в config/routes добавьте строку, которая отправляет запросы формы baseurl/controller/: имя-производителя в действие showummary (или, возможно, новое действие, show_summary_by_vendor_name) [также, если вы планируете использовать baseurl/: vendorname, это тоже хорошо] Для удобства убедитесь, что параметр имеет значение: имя поставщика, а не значение по умолчанию: id

2) Запишите действие контроллера. В файле контроллера отредактируйте свое действие showummary, чтобы дифференцировать его на основе того, вызывалось ли оно с идентификатором или с именем поставщика, или просто написать show_summary_by_vendor_name. (в зависимости от лучших практик и того, на каком пути вы написали в 1. Я не знаю, с верхней части головы, что предпочтительнее) Затем вы можете сделать @vendor = Vendors.find_by_name (params [: vendor_name]) или что-то в этом роде, а затем визуализируйте его так, как вы бы в регулярном шоу.

3) Используйте это как ссылку. Как только вы подтвердите, что baseurl [/controller?]/Имя-производителя работает, и показывает сводку, убедитесь, что все ссылки в вашем приложении и в другом месте используют эту ссылку. С головы до ног я не помню, как сложно интегрировать собственный маршрут в link_to, но я думаю, что это выполнимо. Большинство поисковых систем [google] сильно зависят от ссылок, поэтому хороший SEO будет использовать эти ссылки, а не пронумерованные. Я думаю. Я мало знаю о SEO.