Console Snacks[摘自Advanced Rails Recipes]

上周把Advanced Rails Recipes扫了一遍,受益匪浅,尤其是关于script/console那一段,都是之前没试过的,呵呵,做个摘录。

1. Write Console Methods

在~/.irbrc定义ActvieRecord::Base.connection.select_all方法

# ~/.railsrc
def sql(query)
  ActiveRecord::Base.connection.select_all(query)
end
# ~/.irbrc
if ENV['RAILS_ENV']
  load File.dirname(__FILE__) + '/.railsrc'
end

这样就可以在直接在script/console下面执行sql查询

$ script/console
>> sql 'show databases'

2. Log to the console

ActiveRecord Logger

# ~/.railsrc
def loud_logger
  set_logger_to Logger.new(STDOUT)
end

def quiet_logger
  set_logger_to nil
end

def set_logger_to(logger)
  ActiveRecord::Base.logger = logger
  ActiveRecord::Base.clear_active_connections!
end

ActionPack Logger

# ~/.railsrc
require 'logger'
Object.const_set(:RAILS_DEFAULT_LOGGER, Logger.new(STDOUT))

3. Play in the Sandbox

使用sandbox参数来启动script/console

script/console --sandbox

这样所有的数据库修改都会在退出console时被恢复

4. Access Helpers

直接调用helper方法

helper.pluralize(3, 'blind mouse')

调用自定义的helper方法

helper.extends BlogsHelper
helper.archive_dates

Posted in  rails


给ImageSwitcher增加键盘响应

网上关于ImageSwitcher的例子都是通过Gallery来切换图片的。

我做了一个通过键盘左键/右键来切换图片的例子:

首先是定义键盘的监听器

private View.OnKeyListener mKeyListener = new View.OnKeyListener() {
    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        if (event.getAction() == KeyEvent.ACTION_DOWN) {
            switch (keyCode) {
            case KeyEvent.KEYCODE_DPAD_LEFT:
                showPrevious();
                break;
            case KeyEvent.KEYCODE_DPAD_RIGHT:
                showNext();
                break;
            default:
                break;
            }
        }
        return true;
    }
};

然后是绑定监听器

mSwitcher.setOnKeyListener(mKeyListener);
mSwitcher.setFocusable(true);

特别注意第二句,mSwitcheer.setFocusable(true),只有当mSwitcher获得焦点,键盘响应才有效果!

Posted in  android


android初始化时反射读取所有的drawable

刚开始写android app,需要做一个图片浏览的Activity,本来应该是用一个数组来列出所有的drawable,不过drawable实在太多了,一个个列出来还是件体力活,只能搬出java reflection。代码如下:

try {
    Class klazz = Class.forName("com.huangzhimin.android.R$drawable");
    Field[] fields = klazz.getFields();
    mImageIds = new int[fields.length - 1];
    int i = 0;
    for (Field field : fields) {
        if (!field.getName().equals("icon")) {
            mImageIds[i] = field.getInt(klazz);
            i++;
        }
    }
} catch (Exception e) {
    e.printStackTrace();
}

注意drawable是R的内嵌静态类,所以要写成com.huangzhimin.android.R$drawable。

Posted in  java android


网站被墙

大概是昨天下午吧,网站被墙了。一开始还不知道原因,只是总上不了自己的网站,和hostmonster的客服一说,直接告诉我被墙了,建议我买dedicated ip,试了很久都没用,无奈之下只能花近50美金买20个月的dedicated ip,好不容易网站有点流量了,居然出这种事,只能从头开始了。上twitter抱怨了一把。

Posted in  life


get_response_with_headers

最近在用ruby的net/http写爬虫,发现net/http提供的接口还真不是一般不好用

一开始我是用Net::HTTP.get_response方法,挺简单的,测试起来也不难

http = mock(Net::HTTPSuccess)
http.stubs(:is_a?).with(Net::HTTPSuccess).returns(true)
http.stubs(:body).returns(content)
Net::HTTP.expects(:get_response).with(URI.parse(remote_path)).returns(http)

接着碰到有些网站必须指定User-Agent才能访问,发现get_response方法不能修改http headers,只能换Net::HTTP.start方法

response = start(uri.host, uri.port) do |http|
  http.get(uri.request_uri, headers)
end

可是写测试的时候傻眼了,因为要根据不同的uri.request_uri返回不同的response,不过好像block内部是没法mock。

折腾了半天,最后只能为了测试写个辅助方法

module Net
  class HTTP
    def HTTP.get_response_with_headers(uri, headers)
      response = start(uri.host, uri.port) do |http|
        http.get(uri.request_uri, headers)
      end
    end
  end
end

测试的mock和之前的get_response就一样了

http = mock(Net::HTTPSuccess)
http.stubs(:is_a?).with(Net::HTTPSuccess).returns(true)
http.stubs(:body).returns(content)
Net::HTTP.expects(:get_response_with_headers).with(URI.parse(remote_path), headers).returns(http)

Posted in  ruby rspec http


Fork me on GitHub