IceskYsl@1sters!

程序员…

带了一个moto 的 milestone回来,到家发现我的mac无法给他充电,查了好大一会,找到一个解决的办法,如下:

按照http://blog.gruby.com/2006/11/27/charging-a-motorola-razr-over-usb/ 这个文章说的,下载一个motocharger.app.zip ,然后解压放在applications目录下,运行就可以充电了。

原因不晓,感兴趣的自己链过去了解~

  • 1 Comment
  • Filed under: Android
  • Paperclip,按日期划分目录方法

    一个项目用到了图片上传,不想自己写处理过程了,于是就找找可以使用的插件,看到了Paperclip,大概了看了下代码和使用介绍,比较简洁。

    装上测试了下,整个过程比较顺利,很快就集成了需要的功能,但是具体到我的需求 上,花了点时间,我的需求也比较常见,就是大量的图片不能就存在一个文件夹下(否则这么多的小文件会带来很多的隐患),于是看代码找找其是否支持分目录的方案,我直接基本上都是按时间来分成诸如”2010/0428/”这样的目录,但是找了一圈,发现其提供了timestamp的一个变量,但是其结果比较糟糕,文件夹中还会根据当代的locale出现一些等下,不太合适;

    然后看到其提供了一个:id_partition的参数,其意思是:

    # Returns the id of the instance in a split path form. e.g. returns

    # 000/001/234 for an id of 1234.

    和我预期的差不多,如果决定这个数字还不够,可以修改其代码,如下:
    def id_partition attachment, style_name
    (“%09d” % attachment.instance.id).scan(/\d{3}/).join(“/”)
    end
    你可以再加3位(这下应该足够了,千亿级别的了),分成四个等级
    def id_partition attachment, style_name
    (“%12d” % attachment.instance.id).scan(/\d{3}/).join(“/”)
    end
    然后我们可以按照这个方式专辑实现安装日期类分目录的,代码如下:
    # Returns the timestamp of the instance in a split path form. e.g. returns
    # 2010/0428 for an id of 2010.04.28
    def timestamp_partition attachment, style_name
    attachment.instance_read(:updated_at).strftime(“%Y/%m%d/”)
    # (“%09d” % attachment.instance.id).scan(/\d{3}/).join(“/”)
    end
    然后给model加上:
    has_attached_file :logo, :styles => {:thumb => ’64×64>’, :small => “150×150>” },
    :url => “/upload/:class/:attachment/:timestamp_partition/:id/:style/:basename.:extension”,
    :path => “:rails_root/upload/:class/:attachment/:timestamp_partition/:id/:style/:basename.:extension”
    其得到的结果类似:
    [paperclip] Saving attachments.
    [paperclip] saving /svnroot/eoe/dev/rails/eoemarket/eoeMarket/upload/shops/logos/2010/0428//5/original/me.jpg
    [paperclip] saving /svnroot/eoe/dev/rails/eoemarket/eoeMarket/upload/shops/logos/2010/0428//5/thumb/me.jpg
    [paperclip] saving /svnroot/eoe/dev/rails/eoemarket/eoeMarket/upload/shops/logos/2010/0428//5/small/me.jpg

    [paperclip] Saving attachments.[paperclip] saving /svnroot/eoe/dev/rails/eoemarket/eoeMarket/upload/shops/logos/2010/0428//5/original/me.jpg[paperclip] saving /svnroot/eoe/dev/rails/eoemarket/eoeMarket/upload/shops/logos/2010/0428//5/thumb/me.jpg[paperclip] saving /svnroot/eoe/dev/rails/eoemarket/eoeMarket/upload/shops/logos/2010/0428//5/small/me.jpg

    参考:

    http://jimneath.org/2008/04/17/paperclip-attaching-files-in-rails/

    http://cn.asciicasts.com/episodes/134-paperclip

    http://github.com/thoughtbot/paperclip

    http://gist.github.com/165072

  • 2 Comments
  • Filed under: Ruby&Rails
  • 以前一个项目中直接使用了restful_authentication,耶没怎么管生成的密码是啥样的,最近有几个系统要对接,需要统一用户,于是看了下restful_authentication的密码加密原则,发现其真是负责,一共分成下面几个部分:

    1.定义了一个40位的REST_AUTH_SITE_KEY和一样我常量10的REST_AUTH_DIGEST_STRETCHES;

    2.随机生成一个salt,其salt生成的规则是secure_digest(Time.now, (1..10).map{ rand.to_s }),而secure_digest是Digest::SHA1.hexdigest来生成的,也是40位。

    3.将salt和原始密码,混合前面定义的REST_AUTH_SITE_KEY,反复加密REST_AUTH_DIGEST_STRETCHES次,得到最终的一个digest就是密码了。

    够复杂~ 为啥搞这么负责呢,直接随机salt加双MD5不可逆加密也应该够用了吧。

  • 0 Comments
  • Filed under: Ruby&Rails
  • 前面2个文章说到了在Rails中使用send_file实现断点续传《在rails下实现多线程下载和断点续传》和利用Nginx的X-Accel-Redirect实现发送大文件《使用Nginx的X-Accel-Redirect在Rails中发送文件》,项目中需要两个功能,就把他整合起来,同时发布到github上了,Nginx-X-Accel-Redirect

    简介:
    This Rails plugin allows users to take advantage of nginx’s X-Accel-Redirect header, similar to X-Send-File and Content-Range.

    安装:
    $ script/plugin install git://github.com/IceskYsl/Nginx-X-Accel-Redirect.git

    使用:
    x_accel_redirect “/path/to/file”, :filename => “filename”,:root=>”/path/to/root”

    详细信息:github.com/IceskYsl/Nginx-X-Accel-Redirect

  • 0 Comments
  • Filed under: Ruby&Rails
  • 很多时候,我们会遇到需要一些业务逻辑(例如鉴权)后才将文件发送给客户端,那么如果将附件保存在public目录下将是非常不合适的,为了安全起见,你最好是将其保存在客户端无法直接访问的到的目录下,在处理完业务逻辑后,在将文件发送给客户端,Rails中提供了 send_XXXX来发送文件;

    但是使用Rails的app server(thin,mongrel,passenger etc.)来发送文件(特别是大文件)一直都不是一个靠谱的方案,rails提供的send_file和send_data在理论上是可以工作的,但是其会阻塞进程,消耗内存,等等系列的弊端,而诸如apache,Lighttpd,Nginx等web server在处理静态文件上有着得天独厚的优势。

    于是聪明的人们就想,可以使用app server处理业务逻辑,然后再让web server来接管处理剩下的文件发送,所以就有了mod_xsendfile for Apache2Lighttp中提供的X-Sendfile功能,Nginx自然也有类似的功能,只是其名字不叫X-Sendfile,而是叫X-Accel-Redirect(这个名字好像更容易理解)。 这里主要说Nginx,Apache的自行查阅资料,先了解下原理:

    1. The header must contain a URI
    2. The location should be defined as internal; to prevent the client going directly to the URI

    定义一段配置:

    location /protected/ {
      internal;
      root   /some/path;
    }
    然后在你的应用中:
    add_header("X-Accel-Redirect: /protected/iso.img");
    然后Nginx就接管了你的请求,发送/some/path/protected/iso.img这个文件。
    原理了解了,看看如何使用更快捷,自然是用插件,有人写出了一个插件:X-Accel-Redirect
    = X-Accel-Redirect
    This Rails plugin allows users to take advantage of nginx's X-Accel-Redirect header, similar to X-Send-File.
    == Install
    You should install it as a plugin, running this command on your projects root directory:
         $ script/plugin install git://github.com/goncalossilva/X-Accel-Redirect.git
    == Usage
    X-Accel-Redirect has an equivalent method to Rails <i>send_file</i>, called <b>x_accel_redirect</b>. Using is as easy as:
         x_accel_redirect "/path/to/file", :filename => "filename"
    All <i>send_file</i> options are available using this method. Now you can even let your old <b>:x_sendfile</b> option since the plugin will discard it.
    参考:
    wiki.nginx.org/NginxXSendfile
    
    

    USING NGINX TO SEND FILES WITH X-ACCEL-REDIRECT

    The complete nginx solution to sending flowers and files with rails

    [译]利用Nginx的X-Accel-Redirect头实现下载控制(附带php和rails实例)
  • 1 Comment
  • Filed under: Ruby&Rails
  • 最近一个项目用到了断点续传的需求,找了一些资料,
    ror下文件下载是通过send_file完成的,但是如果使用多线程并支持断点续传的客户端(FlashGet等),send_file是不能正确工作的,原因在于,send_file函数没有对HTTP协议的Range头做相应的支持,并且也不支持HTTP/1.1 206 Partial Content相应
    我修改了send_file函数,并做了一个plugin 将起解压到vendor/plugins/就可以了
    (必要的地方我都写了注释,欢迎大家提出建议和意见)
    记录一下相关的code:

    module ActionController
      module Streaming
        protected
          def send_file(path, options = {})
            raise MissingFile, "Cannot read file #{path}" unless File.file?(path) and File.readable?(path)
    
            options[:length]   ||= File.size(path) # 文件长度
            options[:filename] ||= File.basename(path) # 文件名称
    
            options[:from] ||= 0 # 首偏移量(从哪里开始下载)
            options[:to] ||= options[:length] # 结束位置
    
            m_send_file_headers! options # 设置必要的 http 头
    
            @performed_render = false
    
            if options[:stream]
              render :status => options[:status], :text => Proc.new { |response, output|
                logger.info "Streaming file #{path}" unless logger.nil?
                len = options[:buffer_size] || 8192 # 原来的实现是4K, 不过APUE 上说,8K 要好一些,所有我调整了一下
                File.open(path, 'rb') do |file|
                  file.seek(options[:from].to_i, IO::SEEK_SET) if options[:status] == 206 # 如果是多线程下载,则将流定位到首偏移量位置,从此处开始传输
                  while buf = file.read(len)
                    output.write(buf)
                  end
                end
              }
            else
              logger.info "Sending file #{path}" unless logger.nil?
              File.open(path, 'rb') { |file| render :status => options[:status], :text => file.read }
            end
          end
    
        private
          def m_send_file_headers!(options)
            options.update(DEFAULT_SEND_FILE_OPTIONS.merge(options))
            [:length, :type, :disposition].each do |arg|
              raise ArgumentError, ":#{arg} option required" if options[arg].nil?
            end
    
            disposition = options[:disposition].dup || 'attachment'
    
            disposition <<= %(; filename="#{options[:filename]}") if options[:filename]
    
    	# 先输出一些通用的HTTP头
            headers.update(
              'Content-Type'              => options[:type].strip,  # fixes a problem with extra '\r' with some browsers
              'Content-Disposition'       => disposition,
              'Content-Transfer-Encoding' => 'binary'
            )
    
    	# 判断是否存在Range头,并使用正则表达式匹配 from 和 to
    	# 如果匹配成功,则表示客户端使用多线程下载,同时一定要将http status 设置为 206
            if request.env['HTTP_RANGE'] =~ /bytes=(\d+)-(\d*)/ then # 注意后一个\d*,有一些多线程客户端并不完全符合http协议的要求(例如FlashGet)
              options[:from] = $1
              options[:to] = $2 unless $2.nil? # 如果客户端不标准,就将 to 设置为文件末尾
    
    	  # 匹配成功,设置status 为 206
              options[:status] = 206
    
    	  # 一下3个http 头仅在多线程下载是有用
              headers['Accept-Ranges'] = 'bytes'
              headers['content-Range'] = "bytes #{options[:from]}-#{options[:to]}/#{options[:length]}" # 格式为 bytes from-to/total
              headers['Content-Length'] = options[:to].to_i - options[:from].to_i + 1 # 注意 在多线程下载下,Content-Length 为传输的实际字节数(从0开始算起,所有要+1)
            else
    	  # 非多现场下载
              options[:status] = 200 # 请求正常标志
              headers['Content-Length'] = options[:length] # 非多线程下载下,Content-Length为文件长度
            end
    
            headers['Cache-Control'] = 'private' if headers['Cache-Control'] == 'no-cache'
          end
      end
    end
    

    用法:

    class FileController 〈 ApplicationController
    def download
    #logger.debug request.env['Range'];
    #    request.env.each do |key, value|
    #      logger.debug key + '--------' + value
    #    end
    send_file 'public/jdk.tgz'
    end
    end
    
  • 3 Comments
  • Filed under: Ruby&Rails
  • 昨晚看hero的时候顺带update到mac OS 10.6.3,早上重启机器安装成功,发现rails3无法启动,报:
    /Library/Ruby/Site/1.8/rubygems.rb:334:in `bin_path’: can’t find executable rails for rails-3.0.0.beta (Gem::Exception)
    from /usr/bin/rails:19

    这个错误我之前安装rails3的时候遇到过,解决如下:
    1.先尝试下重新安装rails
    IceskYsl@eoe /svnroot/eoe/dev/rails/eoelogs $ sudo gem install rails –pre
    Password:
    Successfully installed treetop-1.4.5
    1 gem installed
    Installing ri documentation for treetop-1.4.5…
    Installing RDoc documentation for treetop-1.4.5..
    发现多了个treetop的gem,查查是啥:

    Treetop is a language for describing languages. Combining the elegance of Ruby with cutting-edge parsing expression grammars, it helps you analyze syntax with revolutionarily ease.

    再次执行rails,发现
    /Library/Ruby/Site/1.8/rubygems.rb:334:in `bin_path’: can’t find executable rails for rails-3.0.0.beta (Gem::Exception)
    from /usr/bin/rails:19

    还是不行,那就是railties的问题了,重新装下
    IceskYsl@eoe /svnroot/eoe/dev/rails/eoelogs $ sudo gem install railties –pre
    Successfully installed railties-3.0.0.beta
    1 gem installed
    Installing ri documentation for railties-3.0.0.beta…
    Installing RDoc documentation for railties-3.0.0.beta…
    IceskYsl@eoe /svnroot/eoe/dev/rails/eoelogs $ rails -v
    Rails 3.0.0.beta

    OK,可以了~

    很简单,就是在.bash_profile下加了三行.
    export CLICOLOR=1
    export LSCOLORS=exfxcxdxbxegedabagacad

    另外加了一行个性化提示符.
    export PS1=”\[\e[32;1;40m\]\u@\H \w \$ \[\e[0m\]”

    相关的文章参见:

    http://mac.linsheng.me/archives/530.html

    http://www.ibm.com/developerworks/cn/linux/l-tip-prompt/tip01/

    http://hi.baidu.com/rainfish_tju/blog/item/0f54458f849141f0513d9284.html

    配置

    那么应该怎样来配置成我喜欢的颜色呢?下面我们就来详细说一些这些配置。

    ~/.bash_profile是bash shell中当前登录用户的配置文件。bash是“终端”中默认的shell。

    alias ls=”ls -G”是给”ls -G”起了一个别名,当执行ls时,就相当于执行了ls -G。

    CLICOLOR是用来设置是否进行颜色的显示。CLI是Command Line Interface的缩写。
    LSCOLORS是用来设置当CLICOLOR被启用后,各种文件类型的颜色。LSCOLORS的值中每两个字母为一组,分别设置某个文件类型的文字颜色和背景颜色。LSCOLORS中一共11组颜色设置,按照先后顺序,分别对以下的文件类型进行设置:

    directory
    symbolic link
    socket
    pipe
    executable
    block special
    character special
    executable with setuid bit set
    executable with setgid bit set
    directory writable to others, with sticky bit
    directory writable to others, without sticky bit
    LSCOLORS中,字母代表的颜色如下:

    a 黑色
    b 红色
    c 绿色
    d 棕色
    e 蓝色
    f 洋红色
    g 青色
    h 浅灰色
    A 黑色粗体
    B 红色粗体
    C 绿色粗体
    D 棕色粗体
    E 蓝色粗体
    F 洋红色粗体
    G 青色粗体
    H 浅灰色粗体
    x 系统默认颜色
    所以,如果我们想把目录显示成红色,就可以把LSCOLORS设置为bxfxaxdxcxegedabagacad就可以了

  • 0 Comments
  • Filed under: *UNIX & Mac
  • expire_list_cache in cache_fu

    cache_fu在过期单个记录的时候很方便,但是对以那些列表分页的就有点弱了,没法过滤以制定前缀的key来过滤,所以变通下,需要用过loop来过滤,如下是个例子:

    #expire_list_cache
    def expire_caches
    Song.expire_cache(self.id)
    ApkFile.expire_cache(self.main_apk_file_id) if self.main_apk_file_id
    AppStat.expire_cache("app_stat#{self.id}")
    0.upto(PAGES) do |page|
    SongScreenshot.expire_cache("song_screenshots#{self.id}#{page}#{PER_PAGE}")
    Song.expire_cache("list_items_status_state:11#{"updated_at desc"}#{page}#{PER_PAGE}")
    Song.expire_cache("list_items_in_category_status_state:#{self.category_id}11#{"updated_at desc"}#{page}#{PER_PAGE}")
    Song.expire_cache("items_in_autthor:#{self.author_id}11#{"updated_at desc"}#{page}#{PER_PAGE}")
    end
    end

  • 0 Comments
  • Filed under: Ruby&Rails
  • 用了acts_as_taggable_on_steroid和will_paginate插件,发现不能分页,查找解决办法,如下得最方便:
    options = Product.find_options_for_find_tagged_with(params[:tag_name],:order => “updated_at DESC”).merge(:page => params[:page] ||1,:per_page =>20 )
    @products = Product.paginate(options)

  • 0 Comments
  • Filed under: Uncategorized
  • Page::页面

    Calendar::日历

    September 2010
    M T W T F S S
    « Aug    
     12345
    6789101112
    13141516171819
    20212223242526
    27282930  

    RSSTwitter: iceskysl