Прежде чем вдаваться в подробности, я прочитал эти сообщения, чтобы безуспешно попытаться найти решение: один, два, три
При этом: я [новичок] и создаю ecomm-сайт по продаже подержанной одежды, обуви и предметов декора.
В моей структуре есть только одна модель Product и связанный контроллер и таблица. Каждый «продукт» имеет одну из трех различных основных категорий, которые я использую, чтобы различать и создавать 3 разных URL-адреса.
Мои маршруты выглядят так:
Rails.application.routes.draw do
root to: 'pages#home'
get 'clothing', to: 'products#clothing'
get 'clothing/:id', to: 'products#show'
get 'shoes', to: 'products#shoes'
get 'shoes/:id', to: 'products#show'
get 'home', to: 'products#home'
get 'home/:id', to: 'products#show'
get 'products/new', to: 'products#new'
post 'products', to: 'products#create'
end
Мой products_controller выглядит так:
class ProductsController < ApplicationController
before_action :set_all_products
before_action :set_one_product, only: [:show]
def shoes
@all_shoe_products = @all_products.where(main_category_id: MainCategory.find_by_name("shoes").id)
end
def clothing
@all_clothing_products = @all_products.where(main_category: MainCategory.find_by_name("clothes").id)
end
def home
@all_home_products = @all_products.where(main_category: MainCategory.find_by_name("housewares").id)
end
def show
end
def new
@new_product = Product.new
end
private
def set_one_product
@product = Product.find(params[:id])
end
def set_all_products
@all_products = Product.all
end
end
И при записи <%= link_to clothing_path(product) %> ('product' является заполнителем в цикле .each) я получаю путь: root/clothing.[:id], а не root/clothing/[:id].
Я знаю, что делаю ошибку соглашения, и попытка иметь 3 разных URL-адреса в одном контроллере может оказаться там, где я ошибаюсь.
Примечание. Если вручную ввести root/clothing/[:id] в адресную строку, товар будет возвращен правильно.





Когда вы это сделаете:
get 'clothing', to: 'products#clothing'
get 'clothing/:id', to: 'products#show'
в вашем routes.rb он создает эти маршруты (которые вы можете увидеть, выполнив rake routes в вашей консоли):
clothing GET /clothing(.:format) products#clothing
GET /clothing/:id(.:format) products#show
Как видите, clothing_path направляется к /clothing, а не к /clothing/:id. Итак, когда вы это сделаете:
<%= link_to clothing_path(product) %>
rails добавляет идентификатор как .id (что вы и испытываете).
Рад, что это прояснило ситуацию. Кстати, ваш вопрос был: «Почему мой URL-адрес Rails отображает URL-адрес с точкой, а не с косой чертой?». Итак, я ответил на этот вопрос. «Как починить?», «Как уберечь рельсы от…» и т. д. - это разные вопросы.
@jvillian здесь хорошо объясняет причину проблемы, хотя я хотел бы предложить небольшой рефакторинг в качестве решения.
Это может быть немного больше работы, хотя вам, вероятно, будет лучше с отдельными контроллерами для shoes, clothing и home и следовать дизайну RESTful. Это позволит вам использовать resources в вашем файле маршрутов.
Например, ваш shoes_controller.rb будет выглядеть следующим образом:
class ShoesController < ApplicationController
before_action :set_all_products
before_action :set_one_product, only: [:show]
def index
@all_shoe_products = @all_products.where(main_category_id: MainCategory.find_by_name("shoes").id)
end
def show
end
private
def set_one_product
@product = Product.find(params[:id])
end
def set_all_products
@all_products = Product.all
end
end
И тогда маршруты для их определения будут:
resources :shoes, only: [:index, :show]
Вы следуете этому шаблону для других ресурсов, и у вас будет красиво разделенный код, соответствующий хорошим соглашениям Rails.
Это сгенерирует маршруты по мере того, как вы:
shoes GET /shoes(.:format) shoes#index
shoe GET /shoe/:id(.:format) shoes#show
Это решит вашу проблему и даст вам красиво оформленное приложение - также есть возможность экстраполировать часть кода, совместно используемого между новыми контроллерами, хотя это звучит как дополнительная задача :)
Надеюсь, это поможет - дайте мне знать, если у вас возникнут какие-либо вопросы или отзывы.
Я нашел решение, хотя мне кажется логической загадкой, почему оно работает.
В маршрутах .....
get 'clothing', to: 'products#clothing'
get 'clothing/:id', to: 'products#show', as: 'clothing/item'
На странице показатель ....
<%= link_to clothing_item_path(product) do %>
Это дает правильную структуру URL: root/clothing/[:id]
Во время тестирования я ожидал: root/clothing/item/[:id]
... хотя я предпочитаю результат моим ожиданиям
Рад, что у тебя все получилось. Я полагаю, что это результат того, что Rails продезинфицировал / в as: 'clothing/item' до подчеркивания: вы бы достигли того же результата с as: 'clothing_item', который, возможно, немного более читабелен. Я бы порекомендовал прочитать мой ответ - на ранних этапах стоит потратить время, чтобы правильно структурировать приложение, что может избежать изрядной боли в дальнейшем :) Надеюсь, что остальная часть проекта пойдет хорошо.
Я думаю, что вам нужны параметризованные маршруты, например:
get ':product_line', to: 'products#index'
get ':product_line/:id', to: 'products#show'
Это позволит вам создавать любое количество пользовательских линеек продуктов без необходимости определять новые методы в вашем контроллере. Если предположить, что в вашей модели product_line есть атрибут Product, контроллер будет выглядеть так:
class ProductsController < ApplicationController
def index
@product_line = params[:product_line]
@products = Product.where(product_line: @product_line)
end
def show
@product_line = params[:product_line]
@product = Product.find(params[:id])
end
end
И ваши views / products / index.html.erb будут выглядеть так:
<p id = "notice"><%= notice %></p>
<h1><%= @product_line %></h1>
<table>
<thead>
<tr>
<th>Description</th>
<th>Price</th>
<th></th>
</tr>
</thead>
<tbody>
<% @products.each do |product| %>
<tr>
<td><%= product.description %></td>
<td><%= product.price %></td>
<td><%= link_to 'Show', "#{@product_line}/#{product.id}" %></td>
</tr>
<% end %>
</tbody>
</table>
Обратите внимание, что link_to больше не может использовать вспомогательный метод Rails для генерации URL-адреса. Тебе придется сделать это самому.
Прелесть этого подхода заключается в том, что пользователи могут вводить ЛЮБУЮ линейку продуктов в URL-адрес. Если у вас была эта линейка продуктов (например, «sporting_goods»), покажите ее. Если нет, отобразите страницу с благодарностью за проявленный интерес и зарегистрируйте тот факт, что кто-то запросил эту линейку продуктов, чтобы вы могли оценить интерес по мере расширения своих предложений.
К тому же это ОТДЫХ! Ура!
Способ решения этой проблемы в Rails - создание вложенного ресурса:
resources :categories do
resources :products, shallow: true
end
Это вложит маршруты сбора так, чтобы вы получили GET /categories/:category_id/products.
Хотя это может быть не так коротко, как ваши тщеславные маршруты, но он гораздо более универсален, поскольку позволяет вам показывать продукты для любой потенциальной категории без раздувания вашей кодовой базы.
Вы бы настроили контроллер так:
class ProductsController < ApplicationController
before_action :set_category, only: [:new, :index, :create]
# GET /categories/:category_id/products
def index
@products = @category.products
end
# GET /categories/:category_id/products/new
def new
@product = @category.products.new
end
# POST /categories/:category_id/products
def new
@product = @category.products.new(product_params)
# ...
end
# ...
private
def set_category
@category = MainCategory.includes(:products)
.find_by!('id = :x OR name = :x', x: params[:id])
end
end
Вы можете ссылаться на продукты любой категории, используя помощник по именованному пути category_products_path:
link_to "#{@category.name} products", category_products_path(category: @category)
Вы также можете использовать полиморфные помощники по путям:
link_to "#{@category.name} products", [@category, :products]
form_for [@category, @product]
redirect_to [@category, :products]
Если вы хотите направить невложенный GET /products и вложенный GET /categories/:category_id/products к разным контроллерам, можно использовать опцию модуля:
resources :products
resources :categories do
resources :products, only: [:new, :index, :create], module: :categories
end
Это направит вложенные маршруты к Categories::ProductsController.
Привет и спасибо за то, что уделили время ответу. Это я полностью понимаю, но не знаю, как это исправить? Я знаю, что обычное соглашение в показатель и показывать в контроллере - это пути множественное число и единственное число соответственно - хотя я не уверен, как расколоть этот орех здесь