Can Rails Routing Helpers (i.e. mymodel_path(model)) be Used in Models?
假设我有一个叫Thing的Rails模型。它有一个URL属性,可以选择设置为Internet上的某个URL。在视图代码中,我需要执行以下操作的逻辑:
1 2 3 4 5
| <% if thing.url.blank? %>
<%= link_to('Text', thing_path(thing)) %>
<% else %>
<%= link_to('Text', thing.url) %>
<% end %> |
这种观点中的条件逻辑是丑陋的。当然,我可以构建一个助手函数,它将视图更改为:
1
| <%= thing_link('Text', thing) %> |
号
这解决了冗长的问题,但我更喜欢在模型本身中拥有功能。在这种情况下,视图代码为:
1
| <%= link_to('Text', thing.link) %> |
显然,这需要模型上的链接方法。它需要包含以下内容:
1 2 3
| def link
(self.url.blank?) ? thing_path(self) : self.url
end |
。
就问题而言,thing_path()是模型代码中未定义的方法。我假设有可能将一些辅助方法"拉入"到模型中,但是怎么做呢?路由只在应用程序的控制器和视图层上运行,这有什么真正的原因吗?我可以考虑很多情况,模型代码可能需要处理URL(与外部系统集成等)。
- 一个用例是:在保存后从goo.gl生成简短的url,
- 如果要添加视图逻辑,可能需要将模型包装在演示者中,这将使MVC层保持分离。请参见draper(github.com/jcasimir/draper)。
- 另请参见api.rubyonrails.org/classes/actionspatch/routing/url for.ht&zwnj;&8203;ml文档中的"命名路由的URL生成"部分。
在Rails 3、4和5中,可以使用:
1
| Rails.application.routes.url_helpers |
。
例如
1 2
| Rails.application.routes.url_helpers.posts_path
Rails.application.routes.url_helpers.posts_url(:host =>"example.com") |
- Ypu可以将其包含到任何模块中,然后您可以访问URL助手。谢谢
- 避免在任何地方复制您的:host选项,并在环境配置文件中设置一次:Rails.application.routes.default_url_options[:host] = 'localhost:3000'。
- 这在Rails 4中工作吗?我没办法让它工作。
- 我也不能让它在4号轨道上工作。:(
- Rails.application.routes.url_helpers在4号轨道上为我工作。
- 在Rails v3.2.18中,我可以将self.routes.default_url_options[:host] = 'www.example.com'添加到我的config/application.rb中,使它在任何地方都可用。可能会将其移动到config/environments/*.rb文件中,以便为每个环境模式定制它。
- include Rails.application.routes.url_helpers在Rails 4.1中为我工作
- 如果您只需要路径,那么可以使用:only_path=>true作为选项而不传递主机参数。
- 这似乎是个不错的选择:hawkins.io/2012/03/&hellip;
- 轨道工程4.2
- 在Rails 4.2中,您已经在模型中本地定义了default_url_options。@Renarssirotins链环对我很有效,使之干燥。
- 在Rails 5.1.5中为我工作。
我自己就找到了解决办法。在模型代码中,只需输入:
对于轨道<=2:
1
| include ActionController::UrlWriter |
号
对于轨道3:
1
| 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。
- 我得到nomethodError(未定义的方法"优化路由生成?"对于)当我尝试此操作时
您还可能发现以下方法比包括每种方法更干净:
1 2 3 4 5 6 7
| class Thing
delegate :url_helpers, to: 'Rails.application.routes'
def url
url_helpers.thing_path(self)
end
end |
。
- 关于这一点的文档似乎很难找到,因此这里有一个关于在ActiveSupport中使用委托的适当链接。simonecalletti.com/blog/2009/12/inside ruby on rails delegat&zwnj;&8203;e
- 我得到一个undefined local variable or method 'url_helpers' for Event:Class错误…:(
- 我得到了undefined method url_helpers。我该怎么办?
- @同样,你确定你已经使用了delegate选项来链接在类声明之后编写的帮助程序了吗?
- 不起作用,但可能只有当您创建自己的class时才起作用,如答案所示。如果您的模型类已经扩展了< ApplicationRecord,那么这将不起作用?
任何与视图中显示内容有关的逻辑都应该委托给一个助手方法,因为模型中的方法严格用于处理数据。
以下是您可以做的:
1 2 3 4 5 6 7 8 9
| # 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) %> |
- 在这种情况下,我不喜欢helper方法:当我查看link_to_thing()时,我必须决定这是一个特定的对象还是应用程序范围的helper(很容易是两者之一)。我需要考虑检查2个文件的来源。thing.link对源文件毫无疑问。
- 另外,如果我需要在rake任务中使用这个功能(也许导出一个csv文件,内容为url),该怎么办?在这种情况下,直接使用模型也会更好。
- 但不同之处在于,链接"to"在模型中不可用,因为它是一个ActionView助手。所以,这是行不通的。你可以黑一些模型中的属性默认值,所以如果没有设置,它将默认为某个值,但这取决于你自己。
- 随着Web服务API的增长,通常模型需要用自己的数据联系外部资源并提供回调URL。例如,一个照片对象需要将自己发布到socialmod,当执行调节时,socialmod将调用该照片的URL。一个after-create()钩子可以发布到socialmod,但是您如何知道回调URL?我认为作者自己的答案很有道理。
- 虽然从严格的技术意义上讲你是对的,但有时人们只需要一些东西就可以工作,而不必剃光每只牦牛的毛,这样就可以避免违反某些神圣的设计模式或你拥有的东西,也许他们需要得到URL,并将其存储在数据库中,这样模型就可以很方便地知道如何做到这一点。在来回传递东西的过程中,有时规则会被打破。
- 如果你需要打破一个简单模型的规则知道他的网址…好吧,你的代码确实有问题。
我真的很喜欢用干净的溶液。
1 2 3 4 5 6 7 8 9 10 11
| 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_when_and_wherewhere_you want/
虽然可能有一种方法,但我倾向于将这种逻辑排除在模型之外。我同意您不应该将其放在视图中(保持精简),但是除非模型将URL作为一段数据返回给控制器,否则路由资料应该在控制器中。
- 回复:"除非模型将URL作为一个数据块返回"。这就是这里发生的事情…模型"拥有"这段数据,它要么是指向站点内或站点外URL的链接。在某些情况下,URL是从Rails路由生成的。在其他情况下,URL是用户提供的数据。
(编辑:忘记我以前的胡言乱语…)
好吧,在某些情况下,您可能会转到模型或其他URL…但我并不认为这属于模型,视图(或者模型)听起来更合适。
关于路由,据我所知,路由是用于控制器中的操作(wich通常"神奇地"使用视图),而不是直接用于视图。控制器应处理所有请求,视图应显示结果,模型应处理数据并将其提供给视图或控制器。我听过很多人在这里谈论通往模型的路线(到目前为止,我都开始谈论它),但据我所知,路线是通向控制器的。当然,许多控制器都是一个模型的控制器,通常称为sController(例如,"用户控制器"是模型"用户"的控制器)。
如果您发现自己在视图中编写了大量的逻辑,请尝试将逻辑移动到更合适的地方;请求和内部通信逻辑可能属于控制器,与数据相关的逻辑可能被放置在模型中(但不包括显示逻辑,其中包括链接标记等),而与显示相关的逻辑将被放置在一个助手。
- 假设你有一个图像模型。如果图像有一个与之相关联的外部URL,则指向该URL。否则,指向图像的显示页面上载图像?只是个主意。
- 这个不太一般的例子如何:链接到"全尺寸图像",image.link模型中的链接方法要么链接到站点URL(imageu path),要么链接到Flickr URL(如果用户提供了一个和.url)。