假设我有一个名为 Thing 的 Rails 模型。 Thing 有一个 url 属性,可以选择将其设置为 Internet 上某处的 URL。在视图代码中,我需要执行以下操作的逻辑:
<% if thing.url.blank? %>
<%= link_to('Text', thing_path(thing)) %>
<% else %>
<%= link_to('Text', thing.url) %>
<% end %>
视图中的这种条件逻辑很丑陋。当然,我可以构建一个辅助函数,它将视图更改为:
<%= thing_link('Text', thing) %>
这解决了冗长的问题,但我真的更喜欢模型本身的功能。在这种情况下,视图代码将是:
<%= link_to('Text', thing.link) %>
这显然需要模型上的链接方法。以下是它需要包含的内容:
def link
(self.url.blank?) ? thing_path(self) : self.url
end
就问题而言,thing_path() 是模型代码中未定义的方法。我假设可以将一些辅助方法“引入”到模型中,但是如何?路由只在应用程序的控制器和视图层运行是否有真正的原因?我可以想到很多模型代码可能需要处理 URL(与外部系统集成等)的情况。
在 Rails 3 及更高版本中:
Rails.application.routes.url_helpers
例如
Rails.application.routes.url_helpers.posts_path
Rails.application.routes.url_helpers.posts_url(:host => "example.com")
我自己找到了如何做到这一点的答案。在模型代码中,只需输入:
对于 Rails <= 2:
include ActionController::UrlWriter
对于 Rails 3:
include Rails.application.routes.url_helpers
这神奇地使 thing_path(self)
返回当前事物的 URL,或 other_model_path(self.association_to_other_model)
返回某个其他 URL。
include Rails.application.routes.url_helpers
您可能还会发现以下方法比包含所有方法更干净:
class Thing
delegate :url_helpers, to: 'Rails.application.routes'
def url
url_helpers.thing_path(self)
end
end
undefined local variable or method 'url_helpers' for Event:Class
错误... :(
undefined method url_helpers
。我要做什么?
class
时才有效,如答案所示。如果您的 Model 类已经扩展了 < ApplicationRecord
这将不起作用?
任何与视图中显示的内容有关的逻辑都应该委托给辅助方法,因为模型中的方法严格用于处理数据。
这是您可以执行的操作:
# In the helper...
def link_to_thing(text, thing)
(thing.url?) ? link_to(text, thing_path(thing)) : link_to(text, thing.url)
end
# In the view...
<%= link_to_thing("text", @thing) %>
我真的很喜欢遵循干净的解决方案。
class Router
include Rails.application.routes.url_helpers
def self.default_url_options
ActionMailer::Base.default_url_options
end
end
router = Router.new
router.posts_url # http://localhost:3000/posts
router.posts_path # /posts
来自http://hawkins.io/2012/03/generating_urls_whenever_and_wherever_you_want/
虽然可能有一种方法我会倾向于将这种逻辑排除在模型之外。我同意你不应该把它放在视图中(keep it skinny),但除非模型将 url 作为一条数据返回给控制器,否则路由的东西应该在控制器中。
(编辑:忘记我之前的唠叨......)
好的,在某些情况下您可能会转到模型或其他一些网址......但我真的不认为这属于模型,视图(或者可能是模型)听起来更合适。
关于路由,据我所知,路由是针对控制器中的操作(通常“神奇地”使用视图),而不是直接针对视图。控制器应该处理所有请求,视图应该呈现结果,模型应该处理数据并将其提供给视图或控制器。我在这里听到很多人谈论到模型的路由(到了我几乎开始相信它的地步),但据我所知:路由转到控制器。当然,很多控制器都是一个模型的控制器,通常称为<modelname>sController
(例如“UsersController”是模型“User”的控制器)。
如果您发现自己在视图中编写了大量令人讨厌的逻辑,请尝试将逻辑移动到更合适的位置;请求和内部通信逻辑可能属于控制器,数据相关逻辑可能放在模型中(但不包括显示逻辑,包括链接标签等),纯粹与显示相关的逻辑将放在帮助程序中。
:host
选项并在您的环境配置文件中设置一次:Rails.application.routes.default_url_options[:host] = 'localhost:3000'
include Rails.application.routes.url_helpers
在 Rails 4.1 中为我工作