球写一段及其简单的 Ruby 代码

2016-12-08 17:20:29 +08:00
 wadezhao

用 Redmine 管理项目,是 Ruby 写的, Ruby 貌似在 Windows 下处理中文编码有点问题,导致 Redmine 中一些中文文件名的图片显示不正常,我找到解决方法但是不懂 Ruby ,请求帮忙。

需求很简单,下面这个函数是对字符串进行处理,处理后的字符串差不多是这样: /attachments/download/455/02%E5%AE.jpg 我想把最后一个“/”后面的字符删除,就是返回是 /attachments/download/455/ 应该很简单吧,函数如下:

def htmlesc( str, mode=:Quotes )
  if str
    str.gsub!( '&', '&' )
    str.gsub!( '"', '"' ) if mode != :NoQuotes
    str.gsub!( "'", ''' ) if mode == :Quotes
    str.gsub!( '<', '&lt;')
    str.gsub!( '>', '&gt;')
  end
  str
end
7670 次点击
所在节点    Ruby on Rails
30 条回复
wadezhao
2016-12-08 17:20:48 +08:00
哦,忘记说谢谢了。

谢谢。
awolfly9
2016-12-08 17:23:18 +08:00
用 / 分割字符串,然后去掉最后一个再把所有的子串连接,就是你想要的
liprais
2016-12-08 17:23:45 +08:00
str.split("/")[1..-2].join('') 这样?
liprais
2016-12-08 17:24:12 +08:00
@liprais str.split("/")[0..-2].join('') 更正一下
liprais
2016-12-08 17:25:07 +08:00
@liprais "/attachments/download/455/02%E5%AE.jpg".split("/")[0..-2].join("/")
这下感觉对了,最近真是手酸.....
Herobs
2016-12-08 17:28:02 +08:00
@liprais 虽然结果是对的,但是你不觉得做了很多无用功吗
liprais
2016-12-08 17:31:03 +08:00
@Herobs
"请尽量让自己的回复能够对别人有帮助"
lightening
2016-12-08 17:33:05 +08:00
更推荐用自带的 helper 。

> File.dirname('/attachments/download/455/02%E5%AE.jpg')
=> # "/attachments/download/455"

如果想加 "/" 就

> File.dirname('/attachments/download/455/02%E5%AE.jpg') + "/"
Jodal
2016-12-08 18:09:24 +08:00
Jodal
2016-12-08 18:11:54 +08:00
最好还是使用 File 的方法,因为文件名有可能空格之类的,虽然我写的正则包含了 233 (笑
wadezhao
2016-12-08 19:27:22 +08:00
@liprais 谢谢,不过我完全不懂 Ruby ,是把函数最后一行
str
换成
str.split("/")[0..-2].join("/")
么?貌似不行。


@lightening 谢谢。见上,我把
str
换成
File.dirname(str)+ "/"
貌似不行……


@Jodal 你这个我就完全看不懂了…………
wadezhao
2016-12-08 19:31:00 +08:00
@liprais
@lightening
还有一个可能,你们两个的方法都对,但是返回的字符串在别的地方还有处理,识别出了尾部不是图片扩展名,又对字符串做了一些操作,导致最终显示在页面里的内容不对,郁闷了,我这个完全不懂 Ruby 的人还得继续去摸索……
lightening
2016-12-08 20:26:06 +08:00
那你慢慢说,导致的不正常是怎么产生的。原来的图片 url 变成了什么?
102400
2016-12-08 22:05:23 +08:00
"#{File.dirname('/attachments/download/455/02%E5%AE.jpg')}/"
wadezhao
2016-12-08 22:10:21 +08:00
@lightening
嗯,谢谢。
是这样,原始的代码,最终体现到页面上,是这样的:

<img src="/attachments/download/455/02%E5%AE.jpg">

但是这张图片并不显示,如果你直接点击这个图片,会提示一段 HTML 代码,说这个文件不存在,而不存的文件名,并不是"02%E5%AE.jpg",而是一个“乱码.jpg ”,换句话说,直接点击,会告诉你

http://URL/attachments/download/455/乱码乱码乱码.jpg 不存在

看上去,像是 Windows 下的 Ruby ,或者是源代码,对中文文件名的处理有一点问题。
所以我就寻找解决方案,最彻底的方案当然是找到乱码的原因,不过这个不好找,我找了一个妥协的方案,那就是,我发现其实直接把文件名去掉的话,是能显示的,就是说

<img src="/attachments/download/455/">

是可以正常显示的。所以我就想,只要能找到生成这一段代码的 Ruby 源码,生成的字符串,将最后一个“/”之后的字符全删掉,不就行了么?
于是我就找到了这一部分,这一部分的源码是这样的:

def inline_textile_image( text )
text.gsub!( IMAGE_RE ) do |m|
stln,algn,atts,url,title,href,href_a1,href_a2 = $~[1..8]
htmlesc title
atts = pba( atts )
atts = " src=\"#{ htmlesc url.dup }\"#{ atts }"
atts << " title=\"#{ title }\"" if title
atts << " alt=\"#{ title }\""
# size = @getimagesize($url);
# if($size) $atts.= " $size[3]";

href, alt_title = check_refs( href ) if href
url, url_title = check_refs( url )

out = ''
out << "<a#{ shelve( " href=\"#{ href }\"" ) }>" if href
out << "<img#{ shelve( atts ) } />"
out << "</a>#{ href_a1 }#{ href_a2 }" if href

if algn
algn = h_align( algn )
if stln == "<p>"
out = "<p style=\"float:#{ algn }\">#{ out }"
else
out = "#{ stln }<div style=\"float:#{ algn }\">#{ out }</div>"
end
else
out = stln + out
end

out
end
end

虽然我不懂 Ruby ,不过看上去,这一行就是关键:

atts = " src=\"#{ htmlesc url.dup }\"#{ atts }"

看起来,生成<img>的“ src ”内容的,就是这一句,而这个 htmlesc 显然是一个函数,用于处理 URL.DUP 这个变量(这个我并不知道是什么,看字面意思似乎是将 URL 变量复制了一份?)

于是就有了我上面的问题,我找到了最初对 htmlesc 这个函数的定义,希望通过修改它来达到我的目的。

但奇怪的是,修改后,并没有如我想象的写回

<img src="/attachments/download/455/">

写回的是

<img src="">

所以我猜测,也许后面对输出的字符串还是做了什么修改,高度怀疑这几句:

out = ''
out << "<a#{ shelve( " href=\"#{ href }\"" ) }>" if href
out << "<img#{ shelve( atts ) } />"
out << "</a>#{ href_a1 }#{ href_a2 }" if href

但是这个语法我就看不太懂了…………现在就卡在这里了………………
zhs227
2016-12-08 23:12:49 +08:00
把 shelve 贴出来看看
doun
2016-12-08 23:32:41 +08:00
我们也用 redmine ,没有遇到楼主说的问题啊!干嘛要用自己没什么概念的语言做的工具
doun
2016-12-08 23:36:08 +08:00
htmlesc 是做类似 html safe 的动作,肯定很多调用的,不要改这个函数,有问题的话,直接加在这个地方好点
wadezhao
2016-12-08 23:36:50 +08:00
奇怪,函数最后一行的
str
我改成
File.dirname('/attachments/download/455/02%E5%AE.jpg')
可以正常输出 /attachments/download/455

但是如果改成
File.dirname(str)
输出就成空字符串了,百思不得其解………………
wadezhao
2016-12-08 23:41:12 +08:00
@zhs227 我直接把 shelve 删掉了,这一行改成
out << "<img#{ atts } />"
输出没区别。而且看 19 楼我的新发现,应该还是这个 htmlesc 函数的问题


@doun 是的,实际我是又做了一个 htmlesc_img 函数,只在这个地方用 htmlesc_img 函数。上面一直没说,只是方便讨论。
redmine 在 Linux 下没问题,我在 Windows 上用 Bitnami 现成的安装包,根本不需要懂 Ruby ,很容易就部署,但就是有这个中文文件名的问题,我看网上很多人说,而且最新版的 Redmine 一样有这个问题,应该是 Ruby 或者 Windows 的问题。
我用的是工具,是 Redmine ,不是 Ruby ,如果没这个 Bug , Redmine 是很好的一个工具。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/326236

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX