假设我有一个名为Thing的Rails模型。 Thing有一个url属性,能够选择将其设置为Internet上的某个URL。 在视图代码中,我须要执行如下操做的逻辑: app
<% if thing.url.blank? %> <%= link_to('Text', thing_path(thing)) %> <% else %> <%= link_to('Text', thing.url) %> <% end %>
视图中的这种条件逻辑很难看。 固然,我能够构建一个辅助函数,它会将视图更改成: 函数
<%= thing_link('Text', thing) %>
这解决了冗长问题,但我真的更喜欢模型自己的功能。 在这种状况下,视图代码将是: post
<%= link_to('Text', thing.link) %>
显然,这须要模型上的连接方法。 这是它须要包含的内容: url
def link (self.url.blank?) ? thing_path(self) : self.url end
就问题而言,thing_path()是Model代码中未定义的方法。 我假设能够将一些辅助方法“拉入”模型中,可是如何? 是否有一个真正的缘由,路由只在控制器上运行并查看应用层? 我能够想到许多模型代码可能须要处理URL(与外部系统集成等)的状况。 spa
任何与视图中显示的内容有关的逻辑都应该委托给辅助方法,由于模型中的方法严格用于处理数据。 code
这是你能够作的: router
# 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) %>
虽然可能有一种方法我倾向于将这种逻辑排除在模型以外。 我赞成你不该该把它放在视图中( 保持它很瘦 )但除非模型将一个url做为一段数据返回给控制器,不然路由内容应该在控制器中。 ci
(编辑:忘记我之前的唠叨......) 路由
好吧,可能会出现你要去模型或其余网址的状况......但我并不认为这属于模型,视图(或模型)听起来更合适。 get
关于路由,据我所知路由是控制器中的动做(一般“神奇地”使用视图),而不是直接视图。 控制器应处理全部请求,视图应显示结果,模型应处理数据并将其提供给视图或控制器。 我据说不少人在谈论到模型的路线(到目前为止我已经开始接受它了),但据我所知:路线转向控制器。 固然,许多控制器是一个模型的控制器,一般称为<modelname>sController
(例如“UsersController”是模型“User”的控制器)。
若是您发现本身在视图中编写了大量逻辑,请尝试将逻辑移到更合适的位置; 请求和内部通讯逻辑可能属于控制器,数据相关逻辑能够放置在模型中(但不包括显示逻辑,其包括连接标签等),而且纯粹显示相关的逻辑将被放置在帮助器中。
我本身找到了关于如何作到这一点的答案。 在模型代码中,只需:
对于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。
我真的很喜欢干净的解决方案。
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/