有谁知道它是如何工作的,最重要的是如何覆盖它?
我在Rails 5.0.0.1项目上工作。出于实际原因,我们使用命名空间路由,如
namespace :survey do
resources :questions
resources :answers
end
我们相应地设置了Question
和Answer
个模型。
documentation告诉我,帮助器link_to
只需将ActiveRecord实例作为第二个参数传递就可以使用,这意味着在我的情况下简单地在视图中编写以下内容(haml):
= link_to 'Show question', @question
如果没有命名空间,则可以正常工作,但即使路由是命名空间而不是question_path
,也可以使用命名的帮助方法survey_question_path
。关键是我想从ActiveRecord实例决定使用哪个命名路由助手。
有趣的是,Rails知道Question实例将有一个像 question _path这样的命名路由,我只是想不出来。
到目前为止我已经想到了什么:
link_to
的第二个参数使用辅助方法url_for
,然后选择适当的(或不是)命名的路由助手 - 但是如何?model_name
,其中包含route_key
(复数)和singular_route_key
等属性 - 我不确定这与我要查找的内容有什么关系,或者即使它有如何覆盖它。我认为在模型中有一个简单的方法可以覆盖to_partial_path
render @question
或self.controller_path
,在控制器的情况下从另一个视图目录渲染动作,但我不能找到它。
任何帮助都将不胜感激。
修改
经过一些谷歌搜索后,我偶然发现了APIdock中的以下段落(依靠命名路线):
传递记录(如
Active Record
)而不是散列作为options参数将触发该记录的命名路由。查找将在类的名称上进行。因此,传递Workshop对象将尝试使用workshop_path
路由。如果你有一个嵌套路线,例如admin_workshop_path
,你必须明确地调用它(url_for
无法猜出该路线)。
答案 0 :(得分:2)
Rails会使用您的模型model_name
,而且您不应该覆盖该方法。如果您想将Question
转为survey_question_path
来电,那么您需要定义自己的question_path
,并返回survey_question_path
...
def question_path(question)
survey_question_path(question)
end
...或者只是自己使用完整的方法名称。
您还可以使用符号/模型数组,这些数组会直接传递给url_for
:
= link_to 'Show question', [:survey, @question]
答案 1 :(得分:1)
关于你的问题:
- link_to的第二个参数使用辅助方法url_for,其中 然后选择适当的(或不是)命名的路线助手 - 但是如何?
如果你按照你在源代码中提到的#url_for方法,我们将被抛弃,从 ActionView :: RoutingUrlFor 到 ActionDispatch :: Routing :: PolymorphicRoutes
在 ActionDispatch :: Routing :: PolymorphicRoutes#polymorphic_url 方法中,它使用内部类并调用 HelperMethodBuilder.polymorphic_method ,传递所有给定选项(包括您的模型类为'record_or_hash_or_array'(是的,我知道......))。
下面几行,在这个方法的声明中,你会更多地抛出小方法并最终得到这样的方法:
def self.build(action, type)
prefix = action ? "#{action}_" : ""
suffix = type
if action.to_s == "new"
HelperMethodBuilder.singular prefix, suffix
else
HelperMethodBuilder.plural prefix, suffix
end
end
def self.singular(prefix, suffix)
new(->(name) { name.singular_route_key }, prefix, suffix)
end
def self.plural(prefix, suffix)
new(->(name) { name.route_key }, prefix, suffix)
end
正如您所看到的,它将决定是否是 #new 操作,并调用 #singular 或 #plural ,反过来,它将回答你的第二个问题:
- ActiveRecord实例的方法是model_name,它包含route_key(复数)和singular_route_key等属性 - 我不确定这是否与我要查找的内容有关,或者即使它有如何覆盖它。< / LI>
如上所述,这两个方法被赋予一个lambda,它是该内部类的初始值设定项的第一个参数,它将存储为 @key_strategy 。回到** ActionView#UrlFor“,在我给你看的第一个链接上,你看到了这个电话:
else
builder.handle_model_call(self, options)
这将传递给Builder方面的一些方法:
def handle_model(record)
args = []
model = record.to_model
named_route = if model.persisted?
args << model
get_method_for_string model.model_name.singular_route_key
else
get_method_for_class model
end
[named_route, args]
end
def handle_model_call(target, model)
method, args = handle_model model
target.send(method, *args)
end
private
def get_method_for_class(klass)
name = @key_strategy.call klass.model_name
get_method_for_string name
end
def get_method_for_string(str)
"#{prefix}#{str}_#{suffix}"
end
而且,如果我没有遗漏任何内容,最后一个方法将返回您的URL路径。