好的,这是我的问题:
我有一个HomeController
的动作,比如index
,它会为我的网站呈现一个目标网页。该站点还有许多其他控制器,可以实现各种其他功能的操作。
我想在我的主页上使用动态导航栏,而我正在寻找的是HomeController#index
转到我应用中的每个其他控制器并调用一个特定的方法,该方法将返回并反对链接详细信息,例如,HomeController#index
将转到ContactController
并调用方法get_link
,该方法将返回如下内容:
{label: "Contact", url: "/contact"}
同样HomeController#index
会尝试在每个其他控制器上调用get_link
,直到它收集了Array
个链接对象,然后可以将这些对象传递给视图以进行渲染。
我尝试通过模块中的元编程并使用 included
钩子方法(从Sitepoint tutorial获取我的引用)来做到这一点。但那没用。然后我在某处读到了我可能必须使用 ActiveSupport::Concern
来实现这种功能,但我不知道该怎么做。我曾经使用像Drupal和WordPress这样的PHP CMS,但是他们使用钩子实现了这个,这或多或少是我在这里寻找的。有什么想法吗?
答案 0 :(得分:2)
在Rails风格中,MVC控制器不是一堆杂项垃圾的倾销场所。事实上,控制器的唯一公共方法是与HTTP请求相对应的操作:
class ThingsController
before_action :set_thing, except: [:new, :index]
# THIS IS THE "PUBLIC API" OF THE CONTROLLER:
# GET /things
def index
@things = Thing.all
end
# GET /things/:id
def show
end
# EVERYTHING ELSE IS PRIVATE!
private
def set_thing
@thing = Thing.find(params[:id])
end
end
实际上控制器只能由Rails路由器或控制器测试实例化。虽然您可以创建类方法并在控制器上调用它们,但这也是一个巨大的反模式。
根据single responsibility pattern,控制器作业只是在路由层调用时响应HTTP请求。
所以你解决了这样的情况:
如何解决问题取决于用例 - 内容是静态的,还是构建CMS之类的东西?
答案 1 :(得分:0)
首先,您需要急切加载所有控制器:
Rails.application.eager_load!
然后,获取应用中的控制器列表:
controllers = ApplicationController.descendants
从这里你可以调用他们的类方法
controllers[0].get_link
请注意,方法应声明为类方法:
def self.get_link
end
这可能会减慢你的应用程序,因为它急于加载所有东西。总的来说,在我看来,这似乎不是一个好主意,因为你的应用程序中的控制器几乎是静态的。考虑使用路径助手,例如contact_path
。查看Rails Routing Docs了解详情。