使用Rails 3,有没有办法在模型中使用link_to helper或任何帮助器?
答案 0 :(得分:80)
您可能需要在模型中使用link_to。是的,@ andy,这是对MVC的违反,但这并不意味着你应该得到积分而不回答这个问题。
@schwabsauce,比这更容易。如果你在初始化器或其他东西中执行它,那么第一行甚至不是必需的。同样适用于.sanitize和.raw以及其他很棒的其他功能。ActionView::Base.send(:include, Rails.application.routes.url_helpers)
ActionController::Base.helpers.link_to(whatever)
如果您想使用自动回路,可能必须在link_to中执行此操作:
Rails.application.routes.url_helpers.page_path(@page)
答案 1 :(得分:31)
如果您在Rails 3.2.1中执行此操作,请务必遵循Chuck的帖子中提出的建议。看起来这种方法似乎不是一种安全的方法,可以在Rails 3.2.1中的非视图类中包含link_to帮助器。下面概述了一种更安全的方式(在任何情况下都适用于我们)。
当我们在其中一个课程中使用Chuck的帖子时,它最终会产生非常麻烦且难以调试的后果。它最终导致了副作用/错误,这些副作用/错误只出现在非常特殊(和罕见)的环境中。
据我们所知,问题在于这一行:
ActionView::Base.send(:include, Rails.application.routes.url_helpers)
告诉ActionView::Base
要包含Rails.application.routes.url_helpers
,ActionView::Base
显然已经独自完成。让它第二次包含url_helpers
,似乎会导致路由状态的重新初始化(包含ActionDispatch :: Routing :: UrlFor模块的类中的@_routes)。
这导致看似随意且无法解释的"未定义的方法' url_for'为零:NilClass"尝试直接或间接调用 ActionView::Base
之后的url_for方法的视图中的异常第二次包含url_helpers
。
对我们有用的解决方案不是告诉ActionView::Base
再次包含url_helpers
,而是在您可能需要的地方自己包含UrlHelper
模块。
然后,当您需要使用link_to并且可以访问路径时,您可以简单地执行此操作(假设login_path对您的应用程序有效):
include ActionView::Helpers::UrlHelper
...
link = link_to('here', Rails.application.routes.url_helpers.login_path)
我们花了很长时间和很多人为了追踪双包含引起的错误,我只是想在调整Rails基类的行为时警告别人要小心。
答案 2 :(得分:5)
我得到了以下内容:
include ActionView::Helpers::UrlHelper
include ActionController::UrlFor
include Rails.application.routes.url_helpers
cattr_accessor :controller
def controller; self.class.controller; end
def request; controller.request; end
然后在我的控制器中我填充了属性(从头创建一个控制器需要在参数哈希中有大量数据)。
Lead.controller = self
答案 3 :(得分:3)
link_to helper,MVC违规
安迪说,
如果你在模型中生成HTML,你可能需要仔细研究你正在做什么以及为什么。
网址助手
另一方面,URL通常在视图控制器代码之外,在各种服务/表单/ api / ...类中派上用场,例如,甚至在模型中,如果必须的话。
是的,Rails.application.routes.url_helpers是一个模块,但这并不意味着你应该把它包含在任何地方或者像Gary所说的那样有趣的东西会开始发生:
https://www.destroyallsoftware.com/blog/2011/one-base-class-to-rule-them-all
你能做的是:
delegate :url_helpers, :to => 'Rails.application.routes'
然后使用,例如
url_helpers.home_url
答案 4 :(得分:0)
如果你想在任何地方使用任何模块的东西并且不介意违反所有的 Ruby 规范,把这个hackery 放到一个服务中:
module View
extend self
class HelperIncluder
include ActionView::Helpers::UrlHelper
end
def link_to(*args)
HelperIncluder.new.link_to(*args)
end
end
现在:
View.link_to('a', 'b') => "<a href=\"b\">a</a>"
答案 5 :(得分:-7)
不是没有hackery。
如果您认为模型中需要link_to
,则可能违反了Model-View-Controller architecture的某些原则。
模型应该是数据和业务逻辑的地方,但生成链接几乎肯定是控制器或视图的工作(或者,特别是Rails,在辅助类中)。