球写一段及其简单的 Ruby 代码 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
wadezhao
V2EX    Ruby on Rails

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

  •  
  •   wadezhao 2016-12-08 17:20:29 +08:00 8199 次点击
    这是一个创建于 3295 天前的主题,其中的信息可能已经有所发展或是发生改变。

    用 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!( '&', '&amp;' ) str.gsub!( '"', '&quot;' ) if mode != :NoQuotes str.gsub!( "'", '&#039;' ) if mode == :Quotes str.gsub!( '<', '&lt;') str.gsub!( '>', '&gt;') end str end 
    30 条回复    2016-12-09 15:44:52 +08:00
    wadezhao
        1
    wadezhao  
    OP
       2016-12-08 17:20:48 +08:00
    哦,忘记说谢谢了。

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

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

    如果想加 "/" 就

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


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


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

    <img src="http://www.v2ex.com/attachments/download/455/02%E5%AE.jpg">

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

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

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

    <img src="http://www.v2ex.com/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="http://www.v2ex.com/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
        16
    zhs227  
       2016-12-08 23:12:49 +08:00
    把 shelve 贴出来看看
    doun
        17
    doun  
       2016-12-08 23:32:41 +08:00 via Android
    我们也用 redmine ,没有遇到楼主说的问题啊!干嘛要用自己没什么概念的语言做的工具
    doun
        18
    doun  
       2016-12-08 23:36:08 +08:00 via Android
    htmlesc 是做类似 html safe 的动作,肯定很多调用的,不要改这个函数,有问题的话,直接加在这个地方好点
    wadezhao
        19
    wadezhao  
    OP
       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
        20
    wadezhao  
    OP
       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 是很好的一个工具。
    doun
        21
    doun  
       2016-12-08 23:49:05 +08:00 via Android
    贴一下你的函数?
    zhs227
        22
    zhs227  
       2016-12-08 23:50:24 +08:00
    你在不同的地方加一点输出,分段查看一下 url 的值。
    lightening
        23
    lightening  
       2016-12-08 23:51:34 +08:00
    这个 htmlesc 还用来出来 title ,见 `htmlesc title`。而且是直接改输入的,不依赖返回值。建议你还是不用动这个方法了。

    `atts = " src=\"#{ htmlesc url.dup }\"#{ atts }"`
    改成
    `atts = " src=\"#{ File.dirname(htmlesc(url.dup)) }\"#{ atts }"`
    liuhaotian
        24
    liuhaotian  
       2016-12-09 08:15:42 +08:00 via iPhone
    我觉得这个有点像是被 URLENCODE 了
    是不是那个 method 出了问题
    wadezhao
        25
    wadezhao  
    OP
       2016-12-09 11:16:03 +08:00
    @lightening 这个方法我试过了,返回的是空(或者是'./'),很奇怪吧
    wadezhao
        26
    wadezhao  
    OP
       2016-12-09 11:52:48 +08:00
    @doun
    @zhs227
    @lightening
    @liuhaotian

    现在最奇怪的,是这样的。首先,我又做了一个函数:
    def htmlesc_img( str, mode=:Quotes )
    if str
    str.gsub!( '&', '&amp;' )
    str.gsub!( '"', '&quot;' ) if mode != :NoQuotes
    str.gsub!( "'", '&#039;' ) if mode == :Quotes
    str.gsub!( '<', '&lt;')
    str.gsub!( '>', '&gt;')
    end
    str #这个地方我叫 [A 行]
    end

    然后把程序中这一句:
    atts = " src=\"#{ htmlesc url.dup }\"#{ atts }"
    改成
    atts = " src=\"#{ htmlesc_img url.dup }\"#{ atts }" #这一行我叫 [B 行]


    现在最诡异的情况在于:
    1 ,如果 B 行我不改动,或者说 htmlesc_img 的代码和 htmlesc 完全相同,或者干脆把 htmlesc_img 这个处理函数去掉,则会返回
    /attachments/download/455/02%E5%AE.jpg
    说明: url.dup 这个变量是有值的,值是待处理的正常值

    2 ,如果我把 A 行改为: File.dirname('/attachments/download/455/02%E5%AE.jpg'),可以正常输出
    /attachments/download/455
    这说明: atts 这个变量后续并没有被再处理,并且 File.dirname 这个函数执行的结果也是正常的

    3 , A 行如果改成
    v_temp = ''
    v_temp = v_temp+ File.dirname(str)
    或者
    v_temp = File.dirname(str)
    或者
    File.dirname(str)
    则返回的字符串是
    . (就是一个点儿)

    A 行如果改成
    str.split("/")[0..-2].join("/")
    则干脆返回一共空字符串

    也就是说,无论我怎么改,也没办法在 htmlesc_img 这个函数内,把 str 这个变量处理,让这个函数返回正确的内容,这太诡异了…………
    zhs227
        27
    zhs227  
       2016-12-09 12:25:09 +08:00   1
    直接用 log 吧,观察输出可能不靠谱。我测试过你这个函数一定是没有任何问题的

    irb(main):001:0> def htmlesc_img( str, mode=:Quotes )
    irb(main):002:1> if str
    irb(main):003:2> str.gsub!( '&', '&amp;' )
    irb(main):004:2> str.gsub!( '"', '&quot;' ) if mode != :NoQuotes
    irb(main):005:2> str.gsub!( "'", '&#039;' ) if mode == :Quotes
    irb(main):006:2> str.gsub!( '<', '&lt;')
    irb(main):007:2> str.gsub!( '>', '&gt;')
    irb(main):008:2> end
    irb(main):009:1> File.dirname(str)
    irb(main):010:1> end
    => :htmlesc_img
    irb(main):011:0> htmlesc_img '/attachments/download/455/02%E5%AE.jpg'
    => "/attachments/download/455"

    用日志或写文件方式,逐行记录,不可能这么诡异的
    wadezhao
        28
    wadezhao  
    OP
       2016-12-09 12:35:10 +08:00
    @zhs227 我怀疑是正斜杠和反斜杠的问题,很可能传进去的值是这样的?

    \attachments\download\455\02%E5%AE.jpg'
    wadezhao
        29
    wadezhao  
    OP
       2016-12-09 14:55:38 +08:00
    我找到原因了,写回页面的代码应该在别的地方还有处理,一言难尽,但我知道大概问题在哪里了,也知道各位告诉我的 File.dirname 这个函数是可用的。

    多谢各位,我继续解决问题了。 :)
    wadezhao
        30
    wadezhao  
    OP
       2016-12-09 15:44:52 +08:00
    解决了,原来 url 这个变量的值,就是'02%E5%AE.jpg',把前面的‘\attachments\download\455\’加上去,另有其他地方处理。

    在 application_helper.rb 里有一个函数: parse_inline_attachments ,是在这里解析最终输出的字符串,其中解析图片 URL 的一行是这样的:
    "src=\"#{image_url}\"#{alt}"

    如楼上各位指点,这一行改成
    "src=\"#{File.dirname(image_url)}\"#{alt}"

    就达到我的目的了。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1220 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 23:51 PVG 07:51 LAX 15:51 JFK 18:51
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86