我甚至不知道如何为此写一个合适的标题。我基于一堆不同的文章拼凑了一些路由代码,现在我想知道我是否已经把自己画成了一个角落。
我有一个NewsArticle模型,我希望链接看起来像这样:
/news # List of all articles
/news/2011 # List of articles published this year
/news/2011/06 # List of articles published this month
/news/2011/06/28 # List of articles published on this day
/news/2011/06/28/my-post-title # Actual article
好的,已经违背了Rails方式,但也是如此。
我的路线设置如下:
controller :news_articles, :via => [:get] do
match '/news(/:year/(/:month(/:day)))' => :index, :constraints => { :year => /\d{4}/, :month => /\d{2}/, :day => /\d{2}/ }
match '/news/:year/:month/:day/:id' => :show
end
请注意,没有:as
声明。那是因为当我添加:as => "news_archive"
之类的东西时,我最终会得到news_archive_path
,这会返回像“/ news?year = 2010& month = 4”这样的愚蠢内容。所以,我排除了那个位并在我的应用程序帮助文件中编写了自己的路径方法:
def news_archive_path(year = nil, month = nil, day = nil)
return "/news" if year.nil?
t = Time.zone.local(year.to_i, month.nil? ? nil : month.to_i, day.nil? ? nil : day.to_i)
if month.nil?
"/news/#{t.year}"
elsif day.nil?
"/news/#{t.year}/#{"%02d" % t.month}"
else
"/news/#{t.year}/#{"%02d" % t.month}/#{"%02d" % t.day}"
end
end
def news_article_path(article)
t = article.published_at.in_time_zone
"#{news_archive_path(t.year, t.month, t.day)}/#{article.friendly_id}"
end
太好了,这一切都在实践中有效。但是现在我遇到了一个问题,我正在测试我的控制器,我想确保在渲染的模板上出现正确的链接。 (哦,是的,我没有保持单独的视图测试,而是在我的控制器测试中使用render_views
。)但测试失败,错误undefined method
news_article_path'为#`。
那么,我是否只是接近这一切并将自己画成一个角落?或者我可以通过某种方式在控制器测试中包含辅助方法来解决这个问题?或者,为了让测试通过并对链接进行硬编码,我是否只是将其吸收?我希望它们能够实现?
答案 0 :(得分:0)
要使news_article_path可用,您需要执行以下操作:
class MyClass
include Rails.application.routes.url_helpers
end
现在将定义MyClass#news_article_path。您可以尝试将url_helpers包含到测试用例中。我最近看到了“堆栈级太深”的错误(它在初始化时创建了“超级”调用的无限递归)。如果它不起作用,请创建自己的视图助手类并执行“MyViewHelper.new.news_article_path”等。
答案 1 :(得分:0)
通过在路径助手中连接字符串来生成路径可能不是一个好主意。相反,只需使用url_for()
方法即可。例如:
def news_article_path(article, options = {})
url_for(options.merge(:controller => :articles,
:action => :show,
:id => article.id,
:year => article.year,
:month => article.month,
:day => article.day))
end
(假设日,月,年作为模型的快速方法添加,例如:
def year
self.published_at.in_time_zone.year
end
对于您的测试,可以通过以下方式包含帮助方法:My helper methods in controller - 或者再次使用url_for
方法。
...那就是说 - 如你所说,在控制器测试中测试视图并不理想。 :)