хотел определить пользовательские маршруты в определенные ресурсы в дополнение к тем, которые Rails определяет по умолчанию. Для этого соответствующие части моего routes.rb
файл выглядит примерно так:хелпер-путь, созданный Rails на основе пользовательского метода REST.
resource :top, only: [:show]
scope module: :top do
resource :reso, only: [:show]
end
get 'foo_reso' => 'top/reso#foo'
get 'bar_reso' => 'top/reso#bar'
Как вы можете видеть, я хочу только маршруты к ResoController
«s методы show
, foo
и bar
. Это работает, как и rake routes
дает:
reso GET /reso(.:format) top/reso#show
foo_reso GET /foo_reso(.:format) top/reso#foo
bar_reso GET /bar_reso(.:format) top/reso#bar
Это работает: нажав на ссылку в приложение, которое доставит вас на маршрут foo_reso
действительно приводит к вызову ResoController#foo
и последующего отображения связанного представления.
Однако, я думал, что определение маршрута было просто немного некрасиво, и вместо определения маршрутов в явной форме, хотел Rails генерировать их автоматически, говоря это, что ресурс имеет два дополнительных метода REST, foo
и bar
(в то же время ограничивая стандартные методы с помощью аргумента only:
).
Я последовал совету в this answer, и изменил routes.rb
к этому:
resource :top, only: [:show]
scope module: :top do
resource :reso, only: [:show] do
member do
get :foo
get :bar
end
end
end
Теперь rake routes
дает:
reso GET /reso(.:format) top/reso#show
foo_reso GET /reso/foo(.:format) top/reso#foo
bar_reso GET /reso/bar(.:format) top/reso#bar
Обратите внимание на разницу между проходами в двух случаях: в то время как помощник путь и действие контроллера # совпадают, путь изменился с /foo_reso(.:format)
на /reso/foo(.:format)
.
(У меня есть все имена ресурсов, которые определены как несчетные в config/initializers/inflections.rb
, поэтому я не получаю автоматическую плюрализацию имен, потому что в моем приложении каждый контроллер связан с определенным экраном, а не с моделью, поэтому плюрализация не подходит для изображения. В этом приложении методы REST действительно больше напоминают вызовы функций, чем операции с ресурсом, поэтому мне нужен другой набор, чем стандарт.)
Теперь, щелкнув ссылку на foo_reso
в приложении приводит к странице ошибки маршрутизации Rails, которая говорит:
No route matches [GET] "/foo_reso"
Любые идеи о том, что я мог бы сделать, чтобы исправить ситуацию, помимо использования моего оригинального решения?
Добавлено редактирование, 2013-07-12:
Как я отмечаю в комментарии ниже, в соответствии с выходом rake routes
, помощник маршрут foo_reso
соответствует контроллер и метод, который я хочу позвонить, top/reso#foo
, и, когда я вручную вводим соответствующий URL-адрес (reso/foo
) в строку URL-адреса, которая работает по назначению. Однако, пытаясь открыть маршрут foo_reso
из приложения, в No route matches [GET] "/foo_reso"
. foo_reso_path
и foo_reso_url
приводят к той же ошибке.
Что может быть проблема? Неужели не ошибка в Rails?
Добавлено редактирование, 2013-07-22:
Для того, чтобы использовать случай немного яснее, идея заключается в том, что, когда пользователь нажимает кнопку «Reset» на странице контроллера reset
метод , который очищает входы и выходы страницы. Я абстрагировал вопрос, изменив фактический идентификатор reset
на foo
. (reso
и еще несколько других идентификаторов также являются результатом «обфускации».) Я продолжу использовать те же переводы для согласованности, но приведенный ниже код должен быть яснее, если вы помните, что на самом деле foo
- это reset
. (bar
- это что-то еще, но это не имеет значения, так как проблема маршрутизации такая же.)
Чтобы ответить на вопросы Тонг Куа и Джон Хиннеган, я использую foo_reso_path
. Соответствующие части файла reso_controller
:
class Top::ResoController < Top::ResoSuperController
# GET /reso
def show
...
@reset_path = "foo_reso"
...
end # show
# GET /foo_reso
def foo
perform_foo_action
redirect_to reso_path
end
...
end
соответствующие части файла app/views/top/reso/show.html.erb
:
<%= render partial: "top/resosuper_inputs", locals: { the_form_path: reso_path } %>
...
<input type="hidden" id="reset_path" name="reset_path" value="<%= @reset_path %>">
форма включает в себя частичную _resosuper_inputs.html.erb
, чьи соответствующие части являются:
<!-- For using the "Reset" button. -->
<%= javascript_include_tag "my_reset_form.js" %>
<%= simple_form_for :filtering_criteria, url: the_form_path, method: :get do |f| %>
... inputs elided ...
<%= f.button :submit, value: "Search" %>
<%= f.button :submit, type: 'button', value: "Reset"), id: 'reset_button' %>
<% end %>
resosuper
является суперкласса двух разных ресурсов, но я не думаю, что это влияет на это дело. Во всяком случае, вот Javascript файл app/assets/javascripts/my_reset_form.js
:
$(document).ready(function() {
/* Hang functionality on the "Reset" button. */
$('#reset_button').click(function() {
var reset_path = $('#reset_path').val();
window.open(reset_path, "_self")
});
})
Это в JQuery, и, как говорится в комментариях, делает кнопку «Reset» открыть путь, значение которого было сохранено в переменной скрытом ввода с идентификатором reset_path
. Это значение было дано этой форме на Top::ResoController
в переменной @reset_path
, а именно, "foo_reso"
.
Имейте в виду, что все это работало нормально, когда я определил foo_reso
в routes.rb
, как это:
get 'foo_reso' => 'top/reso#foo'
Также имейте в виду, что замена foo_reso
с foo_reso_path
или с foo_reso_url
в операторе присваивания в ResoController
не имеет никакого значения.
Места, где я использую foo_reso
, находятся в контроллере и в представлении, так что это не должно быть проблемой.
Ваши предыдущие URL-адреса конечной точки были неверными. Если они являются действиями на ресурсе reso, тогда они должны быть помещены под этим ресурсом. Если вы не ограничивались просто: покажите, у вас будут такие URL-адреса, как/reso,/reso/123,/reso/new. Вот как работают URL-адреса конечных точек REST. –
ОК, я предполагаю, что часть проблемы, с которой я столкнулся, из того, что я сказал в скобке: я пытаюсь использовать «ресурсы» нестандартным образом. В принципе, я хочу, чтобы маршруты вызывали вызовы методов в контроллере. В этом случае ресурсы, с которыми связаны контроллеры, не являются моделями, а скорее экранами. (Приложение является графическим интерфейсом для приложения Java EE, которое обрабатывает фактические ресурсы.) –
Я думаю, что вы немного потерялись в сорняках, переведя это из пространства Java. Ваш контроллер может беспокоиться о переводе вашего URL-адреса на какой-то ресурс в приложении Java. Метод контроллера, который был бы вызван из списка маршрутов, - «top/reso # foo», который переводится в Top :: Reso.foo в вашем контроллере. Каждый член, которого вы добавите, будет работать так. –