我有一个问题。
我有一个视频和评论模型。 如果用户将视频链接插入到评论中,则链接将替换为视频中的标题。
我该如何编写方法?
def to_show_title_instead_of_the_link
body.gsub!(%r{(videos)\/([0-9])}) {|link| link_to link)}
end
我们输入:
http://localhost:3000/videos/1
我们收到:
<a href="http://localhost:3000/videos/1"> test video</a>
答案 0 :(得分:2)
听起来您想要在您的网站上获取给定的网址,并找到该路线的相关参数。这样您就可以以干净,干燥的方式获取视频的id
(如果您的路线发生变化,则不使用可能会在之后中断的正则表达式)。然后,这将允许您查找模型实例并获取其title
字段。此任务的Rails方法是Rails.application.routes.recognize_path
,它返回带有操作,控制器和路径参数的哈希。
在您看来:
# app\views\comments\show.html.erb
# ...
<div class='comment-text'>
replace_video_url_with_anchor_tag_and_title(comment.text)
</div>
# ...
这是辅助方法:
# app\helpers\comments_helper.rb
def replace_video_url_with_anchor_tag_and_title(comment_text)
# assuming links will end with a period, comma, exclamation point, or white space
# this will match all links on your site
# the part in parentheses are relative paths on your site
# \w matches alphanumeric characters and underscores. we also need forward slashes
regex = %r{http://your-cool-site.com(/[\w/]+)[\.,!\s]?}
comment_text.gsub(regex) do |matched|
# $1 gives us the portion of the regex captured by the parentheses
params = Rails.application.routes.recognize_path $1
# if the link we found was a video link, replaced matched string with
# an anchor tag to the video, with the video title as the link text
if params[:controller] == 'video' && params[:action] == 'show'
video = Video.find params[:id]
link_to video.title, video_path(video)
# otherwise just return the string without any modifications
else
matched
end
end
end
我不知道如何做到这一点,但这就是我弄清楚的:
1)Google rails reverse route
,第一个结果是此stackoverflow问题:Reverse rails routing: find the the action name from the URL。答案提到了ActionController::Routing::Routes.recognize_path
。我解雇了rails console
然后尝试了这个,但它已被弃用,并且实际上没有用。
2)然后我google rails recognize_path
。第一个搜索结果是文档,这些文档不是很有帮助。第三个搜索结果是How do you use ActionDispatch::Routing::RouteSet recognize_path?,其第二个解决方案确实有效。
3)当然,我必须重新理解Ruby正则表达式语法和gsub!
,并测试我上面写的正则表达式=)
答案 1 :(得分:1)
我做了重构代码并使用了gem rinku
def links_in_body(text)
auto_link(text) do |url|
video_id = url.match(/\Ahttps?:\/\/#{request.host_with_port}\/videos\/(\d+)\z/)
if video_id.present?
Video.find(video_id[1]).title
else
truncate(url, length: AppConfig.truncate.length)
end
end
end