2013-07-11 2 views
0

хотел определить пользовательские маршруты в определенные ресурсы в дополнение к тем, которые 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, находятся в контроллере и в представлении, так что это не должно быть проблемой.

+1

Ваши предыдущие URL-адреса конечной точки были неверными. Если они являются действиями на ресурсе reso, тогда они должны быть помещены под этим ресурсом. Если вы не ограничивались просто: покажите, у вас будут такие URL-адреса, как/reso,/reso/123,/reso/new. Вот как работают URL-адреса конечных точек REST. –

+0

ОК, я предполагаю, что часть проблемы, с которой я столкнулся, из того, что я сказал в скобке: я пытаюсь использовать «ресурсы» нестандартным образом. В принципе, я хочу, чтобы маршруты вызывали вызовы методов в контроллере. В этом случае ресурсы, с которыми связаны контроллеры, не являются моделями, а скорее экранами. (Приложение является графическим интерфейсом для приложения Java EE, которое обрабатывает фактические ресурсы.) –

+0

Я думаю, что вы немного потерялись в сорняках, переведя это из пространства Java. Ваш контроллер может беспокоиться о переводе вашего URL-адреса на какой-то ресурс в приложении Java. Метод контроллера, который был бы вызван из списка маршрутов, - «top/reso # foo», который переводится в Top :: Reso.foo в вашем контроллере. Каждый член, которого вы добавите, будет работать так. –

ответ

1

Как указано в описании, вот «использование».

# GET /reso 
def show 
... 
    @reset_path = "foo_reso" 
... 
end # show 

Однако все вышесказанное делает только установив переменную @reset_path экземпляра в символьной строки `«foo_reso»(который по совпадению соответствует старому маршруту)

Что плакат действительно хочет:

@reset_path = foo_reso_path 

, который будет генерировать правильный путь /reso/foo в экземпляр переменной @reset_path

S idenote: плакат сделал все необходимое для отладки маршрутов. Большую часть времени вы можете доверять rake routes. Проверка правильности доступа к маршруту - это хорошо, и поэтому проверка правильности использования помощника маршрута тоже очень важна.

0

Краткий ответ: в Rails нет автоматического способа сделать это.

Причина в том, что URL-адрес RESTul основан в основном на формате /controller/action. Значение, если ваш контроллер ResoController имеет 3 метод show, foo и bar, правильная успокоительная реализация приведут к URLS:

/reso 
/reso/foo 
/reso/bar 

Rails может помочь вам достичь этого, и раствор с помощью members в маршрутах, точно так, как вы описали в своем вопросе.

Использование таких URL-адресов, как /foo_reso или /bar_reso - другими словами, /action_controller не является стандартом Rails, а философия основания Rails - «условная конфигурация». Поэтому, если вам действительно нужны, вы должны объявить их вручную

+0

На самом деле, как я только что узнал, ** ** - это автоматический способ определения путей к ресурсам с использованием настраиваемых методов REST. Вы правы в том, что вы не можете определить ** URL **, например '/ foo_reso', но определение пользовательского метода REST' foo' на ресурсе 'reso' ** делает ** автоматически определяет путь ** * * 'foo_reso', который затем преобразуется в URL'/reso/foo', вызов которого преобразуется в вызов метода 'ResoController # foo' - при условии, что я определяю' reso' как несчетный в 'config/initializers '/inflections.rb'; если нет, замените 'resos' и' ResosController' по мере необходимости. –

+0

Ну да, это именно то, что я написал '/ reso/foo' = RESTful можно сделать автоматическим ---'/foo_reso' = не RESTful должно быть сделано вручную – Benj

+0

Опять же, вы правы, если вы имеете в виду ** URL * * '/ foo_reso', но я хотел, чтобы ** названный маршрут **' foo_reso' работал автоматически, после того, как он определил собственный метод REST 'foo' на ресурсе' reso', и это то, что я (наконец) выполнил , (Я использовал термин «путь» непоследовательно в моем вопросе и комментариях, например, я написал «путь» в комментарии выше, когда я должен был сказать «named route», поэтому этот обмен может быть вызван изменением терминологии .) –

0

Хорошо, я выяснил, что проблема. Как часто оказывается, что после рытья в казалось бы загадочную ошибку, решение было очень простым. Мой reso_controller.rb был:

класса Топа :: ResoController < Топ :: ResoSuperController

# GET /reso 
def show 
    ... 
    @reset_path = "foo_reso" 
    ... 
end # show 

Я заменил строку назначения на это:

@reset_path = foo_reso_path 

без кавычек foo_reso_path. Теперь кнопка «Сброс» работает по назначению.

В заключение, следующий делать не работы:

@reset_path = "foo_reso" 
    @reset_path = "foo_reso_path" 
    @reset_path = "foo_reso_url" 
    @reset_path = foo_reso 

И следующий сделать работы:

@reset_path = foo_reso_path 
    @reset_path = foo_reso_url 

ли я сейчас не чувствую себя глупо. Извините за пустую трату времени.

+0

Да, я просто собирался сказать, что :) Строка не равна методу помощника маршрута –

+0

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

+0

ok, если вы его предлагаете :) –

Смежные вопросы