Rails default_url_options 与 path/url-helpers 中的参数冲突
Rails default_url_options conflicts with params in path/url-helpers
在我的 Rails-6.1.4 应用程序中,我在 routing-filter Gem 中引入了 locale
过滤器以允许 [=52] 中的语言区域设置=]-像 /en/articles
这样的路径(对于语言环境“en”)。然后,我发现路径助手在给出 params
参数(或任何可选参数)时失败。
这是模型 Article
的 article_url()
路径助手的测试(最小测试)失败的示例,模型实例为 @article
:
# test/controllers/articles_controller_test.rb
patch article_url(@article, params: { article: my_hash })
导致
# Error output
ArticlesControllerTest#test_should_update:
DRb::DRbRemoteError: No route matches {:action=>"show", :controller=>"articles",
:locale=>#<Article id: 805413029, ...>}, missing required keys: [:id]
(ActionController::UrlGenerationError)
test/controllers/articles_controller_test.rb:58:in `block in <class:ArticlesControllerTest>'
基本上,路径助手 @article
的主要参数是一个模型实例,它似乎以某种方式被路径助手解释为语言环境(!)。
我应该注意到,当 param
(或其他)选项未给出时,我发现路径助手工作正常。因此,只有在给定额外参数时才会出现问题。
什么是合适的解决方案?
我的设置如下
# test_helper.rb (as recommended in the reference of routing-filter)
RoutingFilter.active = false
# application_controller.rb
def default_url_options
Rails.application.default_url_options = Rails.application.routes.default_url_options =
{ locale: I18n.locale }
end
# config/routes.rb
Rails.application.routes.draw do
filter :locale
scope "(:locale)", locale: /en|ja|fr/ do # [EDIT] This scope should be removed;
# It is unnecessary and is sometimes harmful
# as the locale in the path may be doubled.
resources :articles
end
end
这里我用的是head (8d1f1da) of the master branch for routing-filter because the current RubyGems.org version (0.6.3) for it is known not to work with Rails 6.1 (see Issue 75).
事实上,我找到了一个肮脏的解决方法:
article_url(@article, {params: { article: my_hash }}.merge(
ApplicationController.new.default_url_options))
然而,这意味着每次使用带可选参数的帮助程序时都必须编写此 Hash#merge
...这在实践中会非常乏味,因为在测试套件,这当然是违反DRY原则的。
有什么解决办法吗?
简而言之,除了在application_controller.rb
中设置default_url_options
,为了测试在config/routes.rb
中设置 环境如
# config/routes.rb
Rails.application.routes.draw do
filter :locale
default_url_options(locale: I18n.locale) if Rails.env.test?
这似乎是 Rails 6.1 中设置 default_url_options
的方法([编辑] application_controller.rb
中的设置仍然需要对于 development 环境;test 环境需要此设置)。这在测试和开发环境中都工作正常 除了 当在上下文之外调用路径助手时,我的意思是不是从控制器或视图中调用,在这种情况下 OP 的 肮脏的解决方法 解决了问题:
Rails.application.routes.url_helpers.article_url(
article,
{only_path: true}.merge(ApplicationController.new.default_url_options)
)
背景
Gem routing-filter 通过修改路径来工作,就好像路径(的头部)中包含的语言环境单词(如“en”)作为 URL 参数传递一样(如 ?locale=en
),同时从路径中删除语言环境部分。所以设置default_url_options
才是正确的策略。
在撰写本文时 (Rails-6.1.4),Rail's official guide 中的“从 URL 参数设置语言环境”是真的
default_url_options
设置在 app/controllers/application_controller.rb
设置默认语言环境 URL-参数。
但也许描述已过时 — 我的意思是,Rails 6.1 不再准确?
请注意,似乎 default_url_options
在 Rails 6 中引起了麻烦;参见 。
在我的 Rails-6.1.4 应用程序中,我在 routing-filter Gem 中引入了 locale
过滤器以允许 [=52] 中的语言区域设置=]-像 /en/articles
这样的路径(对于语言环境“en”)。然后,我发现路径助手在给出 params
参数(或任何可选参数)时失败。
这是模型 Article
的 article_url()
路径助手的测试(最小测试)失败的示例,模型实例为 @article
:
# test/controllers/articles_controller_test.rb
patch article_url(@article, params: { article: my_hash })
导致
# Error output
ArticlesControllerTest#test_should_update:
DRb::DRbRemoteError: No route matches {:action=>"show", :controller=>"articles",
:locale=>#<Article id: 805413029, ...>}, missing required keys: [:id]
(ActionController::UrlGenerationError)
test/controllers/articles_controller_test.rb:58:in `block in <class:ArticlesControllerTest>'
基本上,路径助手 @article
的主要参数是一个模型实例,它似乎以某种方式被路径助手解释为语言环境(!)。
我应该注意到,当 param
(或其他)选项未给出时,我发现路径助手工作正常。因此,只有在给定额外参数时才会出现问题。
什么是合适的解决方案?
我的设置如下
# test_helper.rb (as recommended in the reference of routing-filter)
RoutingFilter.active = false
# application_controller.rb
def default_url_options
Rails.application.default_url_options = Rails.application.routes.default_url_options =
{ locale: I18n.locale }
end
# config/routes.rb
Rails.application.routes.draw do
filter :locale
scope "(:locale)", locale: /en|ja|fr/ do # [EDIT] This scope should be removed;
# It is unnecessary and is sometimes harmful
# as the locale in the path may be doubled.
resources :articles
end
end
这里我用的是head (8d1f1da) of the master branch for routing-filter because the current RubyGems.org version (0.6.3) for it is known not to work with Rails 6.1 (see Issue 75).
事实上,我找到了一个肮脏的解决方法:
article_url(@article, {params: { article: my_hash }}.merge(
ApplicationController.new.default_url_options))
然而,这意味着每次使用带可选参数的帮助程序时都必须编写此 Hash#merge
...这在实践中会非常乏味,因为在测试套件,这当然是违反DRY原则的。
有什么解决办法吗?
简而言之,除了在application_controller.rb
中设置default_url_options
,为了测试在config/routes.rb
中设置 环境如
# config/routes.rb
Rails.application.routes.draw do
filter :locale
default_url_options(locale: I18n.locale) if Rails.env.test?
这似乎是 Rails 6.1 中设置 default_url_options
的方法([编辑] application_controller.rb
中的设置仍然需要对于 development 环境;test 环境需要此设置)。这在测试和开发环境中都工作正常 除了 当在上下文之外调用路径助手时,我的意思是不是从控制器或视图中调用,在这种情况下 OP 的 肮脏的解决方法 解决了问题:
Rails.application.routes.url_helpers.article_url(
article,
{only_path: true}.merge(ApplicationController.new.default_url_options)
)
背景
Gem routing-filter 通过修改路径来工作,就好像路径(的头部)中包含的语言环境单词(如“en”)作为 URL 参数传递一样(如 ?locale=en
),同时从路径中删除语言环境部分。所以设置default_url_options
才是正确的策略。
在撰写本文时 (Rails-6.1.4),Rail's official guide 中的“从 URL 参数设置语言环境”是真的
default_url_options
设置在 app/controllers/application_controller.rb
设置默认语言环境 URL-参数。
但也许描述已过时 — 我的意思是,Rails 6.1 不再准确?
请注意,似乎 default_url_options
在 Rails 6 中引起了麻烦;参见