Rails маршрутизирует REST с 2 или более элементами (получить и опубликовать) настраиваемый URL-адрес

У меня есть приложение rails, которое я хотел бы исправить. Я новичок в рельсах и не знаю, как это сделать правильно. Есть база данных, модель и таблица со многими продуктами. Я создал для пользователя способ выбрать 2 из этих продуктов из раскрывающегося списка, содержащего записи базы данных. Пользователь выбирает 2 продукта, а затем может их сравнить. Я настроил представление для отображения спецификаций 2 продуктов.

Я уверен, что не следую REST и делаю это неправильно, хотя он работает. Использование операций CRUD в Rails позволяет отображать и индексировать, а также создает URL-адрес с идентификатором продукта для одного такого продукта, я не делал этого так. Вместо этого я передаю переменную экземпляра @product в форму контроллера/представления productpicker и использую возвращенные параметры для поиска элементов базы данных для отображения в контроллере/представлении сравнения.

Что я хотел бы выполнить:

  1. URL-адрес вида www.domain.com/oneproduct-vs-someotherprodct
  2. правильный RESTfull способ получить 2 продукта одновременно и показать их
  3. карта сайта, на которой есть все ссылки, чтобы я мог предоставить их Google для целей SEO. Я предполагаю, что ссылки будут динамическими, и никто не узнает, что у меня есть какой-то продукт или какой-то другой продукт, поэтому карта сайта необходима, как и текст в URL-адресе выше.
  4. Правильный белый список переменных, где это необходимо

Пожалуйста, помогите направить меня в правильном направлении. Большое спасибо, ребята, за помощь нубу.

Что я сделал до сих пор:

Маршруты:

get 'products/pickproducts'

post 'products/pickproducts', to: 'products#compareproducts'

Можно ли сюда добавить слаги?


person akaras222    schedule 09.03.2016    source источник


Ответы (1)


Вот как бы я это сделал.

config/routes.rb

resources :products do # sets up the usual index, new, create, show, edit, update, destroy
  get :compare, on: :collection
end

Вы сможете получить доступ к этому пути в www.example.com/products/compare, и когда у вас есть два идентификатора продукта для передачи, вы можете просто добавить их к URL-адресу: www.example.com/products/compare?product_id1=345&product_id2=432.

(Обратите внимание, что это запрос GET; POST обычно зарезервировано по соглашению для запросов, которые создают записи, а PUT или PATCH — для запросов, которые обновляют записи. GET запросы обычно являются только те, которые также ожидают параметров в самом адресе.)

приложение/контроллеры/products_controller.rb

class ProductsController < ApplicationController
  # ...
  def compare
    @products = Product.all
    @product1 = Product.find(params[:product_id1]) rescue nil
    @product2 = Product.find(params[:product_id2]) rescue nil
  end
  # ...
end

app/views/products/compare.html.erb

(Отказ от ответственности: я раньше не использовал форму для создания запроса GET, но я думаю, что это должно сработать:)

<%= form_tag compare_products_path, method: :get do |f| %>
  <%= select_tag :product_id1, options_from_collection_for_select(@products, 'id', 'name') %>
  <%= select_tag :product_id2, options_from_collection_for_select(@products, 'id', 'name') %>
  <%= f.submit %>
<% end %>

<% if @product1 && @product2 %>
  <%= @product1.id %>
  <%= @product1.brand %>
  <%= @product1.modname %>
  <hr>
  <%= @product2.id %>
  <%= @product2.brand %>
  <%= @product2.modname %>
<% else %>
  Please select two products above to compare.
<% end %>

Единственная часть, в которой я не уверен, — это SEO и веб-сканеры — я не особенно сильно в них вникал, поэтому не могу посоветовать. Вместо этого вы можете установить этот маршрут:

get ':product_id1-vs-:product_id2' => 'products#compare'

... и затем, если это сработает, URL-адреса будут www.example.com/products/-vs- (да, я знаю, что это не очень хорошо) и www.example.com/products/345-vs-432. Однако для compare_products_path теперь потребуются два аргумента, и я не уверен, как вы можете добавить выбранные продукты в URL-адрес, на который указывает форма.

person PJSCopeland    schedule 09.03.2016
comment
Спасибо за предложение. Если я оставлю программу как есть и воспользуюсь методом параметризации для создания строки someproduct-vs-someotherproduct, есть ли способ динамически добавить эту строку к URL-адресу сравнения представлений? если бы был способ сделать это, думаю, я мог бы оставить все как есть. - person akaras222; 09.03.2016
comment
Да, я сам думал об этой проблеме - все еще не уверен, как вы это сделаете. Единственная идея, которая у меня была до сих пор, - это изменить тег <form> с помощью Javascript. - person PJSCopeland; 09.03.2016
comment
Я пытаюсь реализовать то, что вы здесь сказали, но я где-то нарезаюсь. Не могли бы вы объяснить, откуда взялось название в options_from_collection_for_select? - person akaras222; 10.03.2016
comment
О, я не знаю, как называются ваши поля. Я просто предположил, что ваш первичный ключ будет id, а ваше отображаемое имя будет name. Вы должны заменить это тем, что у них есть на самом деле. - person PJSCopeland; 10.03.2016
comment
Я попытался ввести имя поля, одно из имен полей - бренд, выдает ту же ошибку? - person akaras222; 11.03.2016
comment
Я никогда не использовал options_from_collection_for_select и не понимаю, что нужно указывать в имени, кроме имени поля. - person akaras222; 11.03.2016
comment
См. apidock.com/rails/ActionView/Helpers/FormOptionsHelper/. Первый аргумент — это коллекция; второй — это метод отправки каждому элементу для получения атрибута value тега option; и третий — это метод отправки каждому элементу, чтобы текст отображался внутри тега option. - person PJSCopeland; 11.03.2016