我正在开发一个Twitter副本项目,用于我正在尝试使用指向相应用户名的个人资料页面的超链接,在推文中超链接任何@username实例。使用gsub我可以让替换工作,但如果推文有多个不同的@usernames实例,它只用第一个用户名替换它们。这就是我到目前为止所拥有的:
def twet_link_replacer(twet)
if twet.content.include? "@"
username = twet.content.match(/@(\w+)/)
content_tag :p, twet.content.gsub!(/@(\w+)/, link_to(username, '/twets/'+username.to_s.gsub(/@/,""))).html_safe
else
content_tag :p, twet.content
end
end
谢谢!
答案 0 :(得分:2)
你在这里做了太多的工作。当您使用twet.content.include? "@"
时,我没有理由致电gsub
,因为如果找不到gsub
,@
将无法执行任何操作。出于同样的原因,您也不需要if...else
。这样的东西就足够了:
def twet_link_replacer(twet)
new_content = twet.content.gsub(/@(\w+)/) do |username|
link_to(username, "/twets/#{$1}")
end
content_tag :p, new_content
end
这使用gsub
的块参数,让我们将匹配替换为link_to
的结果。在阻止内部,username
是完整匹配的文字(例如"@Jordan"
),$1
是第一个(也是唯一的)捕获组(例如"Jordan"
)。
您的代码还有其他一些问题。首先,不在用户输入上使用html_safe
。我假设twet.content
来自用户输入,因此本质上是不安全的。通过信任它(这是html_safe
所暗示的 - 它告诉Rails,"不要逃避这个字符串,因为我相信它是安全的")你让你的应用程序对XSS攻击敞开大门
其次,当您使用字符串连接或插值(例如"/twets/" + username
或"/twets/#{username}"
)来创建要提供给link_to
的网址或路径时,您需要可能犯了一个错误。这取决于您的路线是什么样的,但是如果您正在使用resourceful routes,那么您应该使用,例如。
# instead of this...
link_to(username, "/users/" + username)
# you can just do this...
link_to(username, user_path(username))
...会自动为您生成一个网址,如果您稍后更改路线,则无法更改您的观看次数或帮助,因为user_path
会随路径自动更改。
同样,这取决于您如何定义路线,但这是您应该尝试的方向。
答案 1 :(得分:1)
问题是您使用两个不同的正则表达式来匹配用户名。将它们结合起来得到你想要的东西。
def twet_link_replacer(twet)
if twet.content.include? "@"
content_tag :p, twet.content.gsub!(/@(\w+)/, link_to('\1', '/twets/\1')).html_safe
else
content_tag :p, twet.content
end
end