我需要在Ruby on Rails中覆盖相当多的路径助手方法,并从中调用super。我的标准方法是:
的 path_helper.rb
def business_path(business)
if params[:city_id] == 2
moscow_business_path(business)
else
super
end
end
但我有很多这些方法,所以我想动态定义它们:
%i[root businesses business ...].each do |path_method|
method_name = "#{path_method}_path"
old_method = method(method_name)
define_method(method_name) do |*args|
if params[:city_id] == 2
public_send("moscow_#{method_name}")
else
old_method.call(*args)
end
end
end
但是我收到了这个错误:
/home/leemour/Ruby/burobiz/app/helpers/path_helper.rb:31:in `method': undefined method `root_path' for class `Module' (NameError)
from /home/leemour/Ruby/burobiz/app/helpers/path_helper.rb:31:in `block in <module:PathHelper>'
from /home/leemour/Ruby/burobiz/app/helpers/path_helper.rb:29:in `each'
from /home/leemour/Ruby/burobiz/app/helpers/path_helper.rb:29:in `<module:PathHelper>'
from /home/leemour/Ruby/burobiz/app/helpers/path_helper.rb:1:in `<top (required)>'
from /home/leemour/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/activesupport-5.1.3/lib/active_support/dependencies.rb:476:in `load'
我猜辅助模块尚未包含在内,因此没有原始路径辅助方法可以使用method(method_name)
进行捕获。然后我想我必须使用self.included
钩子,但我无法理解。如何调整此代码才能使其正常工作? (我不想使用eval)。
答案 0 :(得分:2)
您也可以打包所有的电话
def path_name_for(path_name,*args)
path = "#{path_name}_path"
path.prepend("moscow_") if params[:city] == 2
public_send(path,*args)
end
然后在你的观点中简单地调用
<%= link_to 'Business Path', path_name_for(:business, @business) %>
这使得路由更加清晰,因为它使得有一个自定义实现更加明显,而不是覆盖已知的实现。
这也可能是一种可能性(虽然未经测试,这应该像你现在的代码一样起作用&#34; path_helper.rb&#34;)
module PathHelper
module MoscowRedirect
def self.prepended(base)
%i[...].each do |path_name|
define_method("#{path_name}_path") do |*args|
params[:city] == 2 ? public_send("moscow_#{__method__}",*args) : super(*args)
end
end
end
end
self.prepend(MoscowRedirect)
end