简体   繁体   English

可以在模型中使用Rails路由助手(即mymodel_path(模型))吗?

[英]Can Rails Routing Helpers (i.e. mymodel_path(model)) be Used in Models?

Say I have a Rails Model called Thing. 假设我有一个名为Thing的Rails模型。 Thing has a url attribute that can optionally be set to a URL somewhere on the Internet. Thing有一个url属性,可以选择将其设置为Internet上的某个URL。 In view code, I need logic that does the following: 在视图代码中,我需要执行以下操作的逻辑:

<% if thing.url.blank? %>
<%= link_to('Text', thing_path(thing)) %>
<% else %>
<%= link_to('Text', thing.url) %>
<% end %>

This conditional logic in the view is ugly. 视图中的这种条件逻辑很难看。 Of course, I could build a helper function, which would change the view to this: 当然,我可以构建一个辅助函数,它会将视图更改为:

<%= thing_link('Text', thing) %>

That solves the verbosity problem, but I would really prefer having the functionality in the model itself. 这解决了冗长问题,但我真的更喜欢模型本身的功能。 In which case, the view code would be: 在这种情况下,视图代码将是:

<%= link_to('Text', thing.link) %>

This, obviously, would require a link method on the model. 显然,这需要模型上的链接方法。 Here's what it would need to contain: 这是它需要包含的内容:

def link
  (self.url.blank?) ? thing_path(self) : self.url
end

To the point of the question, thing_path() is an undefined method inside Model code. 就问题而言,thing_path()是Model代码中未定义的方法。 I'm assuming it's possible to "pull in" some helper methods into the model, but how? 我假设可以将一些辅助方法“拉入”模型中,但是如何? And is there a real reason that routing only operates at the controller and view layers of the app? 是否有一个真正的原因,路由只在控制器上运行并查看应用层? I can think of lots of cases where model code may need to deal with URLs (integrating with external systems, etc). 我可以想到许多模型代码可能需要处理URL(与外部系统集成等)的情况。

In Rails 3, 4, and 5 you can use: 在Rails 3,4和5中,您可以使用:

Rails.application.routes.url_helpers

eg 例如

Rails.application.routes.url_helpers.posts_path
Rails.application.routes.url_helpers.posts_url(:host => "example.com")

I've found the answer regarding how to do this myself. 我自己找到了关于如何做到这一点的答案。 Inside the model code, just put: 在模型代码中,只需:

For Rails <= 2: 对于Rails <= 2:

include ActionController::UrlWriter

For Rails 3: 对于Rails 3:

include Rails.application.routes.url_helpers

This magically makes thing_path(self) return the URL for the current thing, or other_model_path(self.association_to_other_model) return some other URL. 这神奇地使thing_path(self)返回当前事物的URL,或者other_model_path(self.association_to_other_model)返回一些其他URL。

You may also find the following approach cleaner than including every method: 您可能还会发现以下方法比包含每种方法更清晰:

class Thing
  delegate :url_helpers, to: 'Rails.application.routes' 

  def url
    url_helpers.thing_path(self)
  end
end

Any logic having to do with what is displayed in the view should be delegated to a helper method, as methods in the model are strictly for handling data. 任何与视图中显示的内容有关的逻辑都应该委托给辅助方法,因为模型中的方法严格用于处理数据。

Here is what you could do: 这是你可以做的:

# 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) %>

I really like following clean solution. 我真的很喜欢干净的解决方案。

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

It's from http://hawkins.io/2012/03/generating_urls_whenever_and_wherever_you_want/ 它来自http://hawkins.io/2012/03/generating_urls_whenever_and_wherever_you_want/

While there might be a way I would tend to keep that kind of logic out of the Model. 虽然可能有一种方法我倾向于将这种逻辑排除在模型之外。 I agree that you shouldn't put that in the view ( keep it skinny ) but unless the model is returning a url as a piece of data to the controller, the routing stuff should be in the controller. 我同意你不应该把它放在视图中( 保持它很瘦 )但除非模型将一个url作为一段数据返回给控制器,否则路由内容应该在控制器中。

(Edit: Forget my previous babble...) (编辑:忘记我以前的唠叨......)

Ok, there might be situations where you would go either to the model or to some other url... But I don't really think this belongs in the model, the view (or maybe the model) sounds more apropriate. 好吧,可能会出现你要去模型或其他网址的情况......但我并不认为这属于模型,视图(或模型)听起来更合适。

About the routes, as far as I know the routes is for the actions in controllers (wich usually "magically" uses a view), not directly to views. 关于路由,据我所知路由是控制器中的动作(通常“神奇地”使用视图),而不是直接视图。 The controller should handle all requests, the view should present the results and the model should handle the data and serve it to the view or controller. 控制器应处理所有请求,视图应显示结果,模型应处理数据并将其提供给视图或控制器。 I've heard a lot of people here talking about routes to models (to the point I'm allmost starting to beleave it), but as I understand it: routes goes to controllers. 我听说很多人在谈论到模型的路线(到目前为止我已经开始接受它了),但据我所知:路线转向控制器。 Of course a lot of controllers are controllers for one model and is often called <modelname>sController (eg "UsersController" is the controller of the model "User"). 当然,许多控制器是一个模型的控制器,通常称为<modelname>sController (例如“UsersController”是模型“User”的控制器)。

If you find yourself writing nasty amounts of logic in a view, try to move the logic somewhere more appropriate; 如果您发现自己在视图中编写了大量逻辑,请尝试将逻辑移到更合适的位置; request and internal communication logic probably belongs in the controller, data related logic may be placed in the model (but not display logic, which includes link tags etc.) and logic that is purely display related would be placed in a helper. 请求和内部通信逻辑可能属于控制器,数据相关逻辑可以放置在模型中(但不包括显示逻辑,其包括链接标签等),并且纯粹显示相关的逻辑将被放置在帮助器中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM