Я пытаюсь изменить функцию - которая в настоящее время принимает только URL (путь) string - чтобы сделать ее более гибкой, чтобы она также принимала в качестве входных данных те же аргументы, которые вы можете передать до url_for
. Проблема в том, что url_for
возвращает полный URL-адрес, включая протокол / хост, и мне нужна только часть пути ...
url_for
имеет замечательную опцию only_path: true
, которая позволяет пропустить добавление протокола / хоста. Это прекрасно работает, если вы передаете его как часть одного хеша url_for
:
main > app.url_for(controller: 'users', action: 'index', only_path: true)
=> "/users"
Но как передавать параметры, когда передаете массив или объект модели в url_for
?
main > app.url_for(user, only_path: true)
ArgumentError: wrong number of arguments (given 2, expected 0..1)
from /gems/actionpack-5.1.6/lib/action_dispatch/routing/url_for.rb:166:in `url_for'
main > app.url_for([user, :notification_preferences], only_path: true)
ArgumentError: wrong number of arguments (given 2, expected 0..1)
/actionpack-5.1.6/lib/action_dispatch/routing/url_for.rb:166:in `url_for'
Ты не можешь! Ясно, что синтаксически невозможно даже передать хэш опций, если вы передаете что-либо, кроме хэша, так как это s arity равно 0..1
, и он принимает только один аргумент: url_for(options = nil)
.
Итак, мой вопрос: есть ли помощник Rails, который принимает те же опции, что и url_for
(включая anchor:
), но возвращает путь?
Полагаю, было бы не сложно добавить один, например, , этот , который использует URI.parse(path).path
(вероятно, то, что я сейчас сделаю) ... но это кажется неэффективным, не элегантным и непоследовательный.
Неэффективно и inelegant , поскольку он генерирует строку, содержащую дополнительную нежелательную информацию, а затем должен проанализировать ее, преобразовать в структурированную структуру данных и затем преобразовать ее обратно в строку без нежелательной информации.
Несогласовано потому что:
Rails включает в себя вариант _path
для каждого _url
помощника по маршруту. Почему у него нет встроенного варианта «пути» url_for
(или он называется и называется ли что-то еще?)?
Другие помощники по маршрутизации, которые принимают объект или массив - например, polymorphic_path
- позволяют также передавать параметры:
Пример: * 1 069 *
main > app.polymorphic_url [user, :notification_preferences], anchor: 'foo'
=> "http://example.com/users/4/notification_preferences#foo"
main > app.polymorphic_path [user, :notification_preferences], anchor: 'foo'
=> "/users/4/notification_preferences#foo"
main > app.polymorphic_path user, anchor: 'foo'
=> "/users/4#foo"
ActionDispatch::Routing::RouteSet
на самом деле имеет path_for
:
# strategy for building urls to send to the client
PATH = ->(options) { ActionDispatch::Http::URL.path_for(options) }
UNKNOWN = ->(options) { ActionDispatch::Http::URL.url_for(options) }
def path_for(options, route_name = nil)
url_for(options, route_name, PATH)
end
# The +options+ argument must be a hash whose keys are *symbols*.
def url_for(options, route_name = nil, url_strategy = UNKNOWN)
options = default_url_options.merge options
...
- просто нет ActionDispatch::Routing::UrlFor
, по-видимому. В любом случае, ActionDispatch::Routing::RouteSet#path_for
похоронен слишком глубоко во внутренних органах, чтобы быть полезным для меня; Мне нужен помощник, который вызывается из контроллера / представления.
Итак, что является хорошим решением для этого, которое является элегантным, совместимым с другими помощниками маршрутизации Rails и относительно эффективным (без URI.parse
)?
Еще лучше, есть ли причина, по которой сигнатура метода встроенного url_for
не может быть просто изменена (в будущей версии Rails путем отправки запроса на выборку), чтобы разрешить как субъекту (объект модели, массив или хеш) и любое количество необязательных options
, которые нужно передать в?
Вероятно, оригинал url_for
был написан до того, как у Руби были ключевые аргументы. Но в настоящее время довольно просто сделать именно это: принять «объект» плюс любое количество опциональных ключевых слов:
def url_for(object = nil, **options)
puts "object: #{object.inspect}"
puts "options: #{options.inspect}"
end
main > url_for ['user', :notification_preferences], anchor: 'anchor'
object: ["user", :notification_preferences]
options: {:anchor=>"anchor"}
=> nil
main > url_for ['user', :notification_preferences], only_path: true
object: ["user", :notification_preferences]
options: {:only_path=>true}
Есть ли причина, по которой мы не смогли / не должны изменить сигнатуру метода url_for
на url_for(object = nil, **options)
?
Как бы вы изменили url_for
/ full_url_for
так, чтобы он оставался максимально совместимым с предыдущими версиями, но также позволял бы вам вызывать его с помощью массива + опции ключевого слова?