Archive for 七月, 2009

ruby on rails:自引用的关联表

Posted on 七月 27th, 2009 in 翻译 | 5 Comments »

原文:http://dizzy.co.uk/ruby_on_rails/contents/self-referential-table-joins
翻译:ssword

本文将展示如何为表创建与自身的关联。例如,一篇文章可以有多个相关文章,抑或一个人可以认识很多人。

设想,你有个表存放一个blog中的所有文章,每篇文章都可以有几篇相似的文章。或者有个储存人物资料的表,人与人之间也可能存在相互的关系。不难看出这是多对多(has_and_belongs_to_many,HABTM)的关联,不过只有一个表。因此这是个自引用的关联:一个人可以认识多个人,这些人还可以认识别的人,等等。

同其他多对多的关联一样,我们需要另加一个中间表,来记录文章之间的关系。只是这里中间表的两个id都是来自article,一个字段记录主文章的id,另一个字段表示相关文章的id。把这个中间表命名为 related_articles,创建一个migration…

create_table "related_articles", :force => true, :id => false do |t|
    t.column "related_article_id", :integer
    t.column "main_article_id", :integer
end

自引用类

回想下,中间表不另必拥有自己的id,因此我们设置:id => false。再看下Article类:

除却在创建关联时添加的冗余内容,Article与其他的类并无二致。在标准的多对多关联中,Rails会自动找到中间表的名字。不过在这里,中间表的名字并非两个Model的连接,它是自引用。因此我们需要添加点额外选项,让它辨认出来:

1
2
3
class Article < ActiveRecord::Base
    has_and_belongs_to_many :related_articles, :class_name => "Article", :join_table => "related_articles", :foreign_key => "main_article_id", :association_foreign_key => "related_article_id"
end

这几个选项又是什么意思呢?

  • :join_table向rails指明了中间表的名字,也就是related_articles。
  • :foreign_key指明了外键的名字,它代表主文章的id,作为相关文章的上一级:称作main_article_id。
  • :association_foreign_key指明了相关文章的外键,也就是”属于”主文章的文章。
  • :class_name表示了当前类的名字,即Article

实现

添加相关文章的界面最好是下拉列表。修改view new.rhtml,让我们可以在添加新文章时添加相关文章。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<% form_for(@article) do |f| %>
 
  <b>Content</b><br />
  <%= f.text_field :content %>
 
  <b>Title</b><br />
  <%= f.text_field :title %>
 
  <b>Related articles</b><br />
  <%= f.collection_select(:related_article_ids, Article.find(:all), :id, :title, {}, :multiple => true) %>
 
  <%= f.submit "Create" %>
 
<% end %>

我们用了helper函数collection_select,结合related_article_ids方法。在定义多对多关联的时候,这个方法就自动生成了,它接受一个id构成的数组来添加到中间表。通过Article.find(:all)获得数据库中的所有文章,交给collection_select格式化输出,这一来在下拉列表中显示:title,而在提交表单的时候就得到了所选的文章:id。同时设置:multiple => true,从而允许多选。

我不讲太多细节了,像如何在多对多关联时使用下拉列表之类,那是另一个话题。不过别担心 – 我很快就会写(看看右边的相关文章,或许在你看到的时候我已经写了!) (译者注:以作者的blog为准)

并行的quicksort

Posted on 七月 24th, 2009 in 备忘 | 9 Comments »

haskell搞并行还是挺方便的。纯函数式没状态嘛,这儿锁啊钥匙啊什么的都不用管了。有个Control.Parallel,里貌似只有两个函数,一个par,表示两个并行计算;一个pseq,表示连续计算。参数都是两个名字。像处理个分治算法啥的,就再合适不过了。于是再次膜拜惰性求值,写起来真的太奇特了。

module Main where
import Control.Parallel
 
--the classic one
qsort :: (Ord a) => [a] -> [a]
qsort [] = []
qsort (x:xs) =
 (qsort lt) ++ [x] ++ (qsort gt)
 where
  lt = filter (<x) xs
  gt = filter (>=x) xs
 
 
--the parallel one
psort :: (Ord a) => [a] -> [a]
psort [] = []
psort (x:xs) =
 sorted_lt `par` sorted_gt `pseq` (sorted_lt ++ [x] ++ sorted_gt) ----unbelieveable,isn't it? :>
 where
  sorted_lt = psort $ filter (<) xs
  sorted_gt = psort $ filter (>=x) xs
 
 
main = do {
 list <- return [5000,4999..1];
 print $ qsort list;
 print $ psort list;
}

profile下,给ghc添加一个编译选项 -prof -O:

ghc --make -prof -O -auto-all quicksort.hs

执行程序,加一个选项 +RTS -p,它会在本目录下生成一个quicksort.prof文件

quicksort +RTS -p

quicksort.prof文件的部分内容:

 Mon Jul 20 16:40 2009 Time and Allocation Profiling Report  (Final)

    quicksort +RTS -p -RTS

 total time  =        6.86 secs   (343 ticks @ 20 ms)
 total alloc = 1,401,627,416 bytes  (excludes profiling overheads)

COST CENTRE                    MODULE               %time %alloc

qsort                          Main                  69.1   49.9
psort                          Main                  30.9   49.9

可见在这台双核的机器上,性能提高了一半多 :)
ps:测试的数据貌似不是很好(按说该用个随机数列),不过知道有这回事就行了~

王猫猫谈Monad

Posted on 七月 20th, 2009 in 笔记 | 19 Comments »

Feather 2009-07-19 21:46:08

世事恰如迷局, 寻人, 失散, 流落, 皈依, 纷乱无绪, 及至谜底解开, 那人却已站立在你面前.

Read the rest of this entry »

试玩vimperator

Posted on 七月 19th, 2009 in 备忘 | 9 Comments »

以前貌似在豆瓣看到有人提起过这vim键操作firefox的插件,当时的第一反应就是蛋疼:有人用导线连了一台cpu,有人只用emacs上网,有人用《最后的晚餐》里的面包谱曲子,有人的妈妈找他回家吃饭…拉门,我确实都想到一块去了。

好吧,暑假在家无所事事,我又蛋疼了,装vimperator。简单熟悉一下后发现这东西还是很成熟的,除去猎奇者,拿它日常使用的也大有人在。装上之后ff的导航栏和书签栏都消失了,习惯chrome的同学们可能会找到一点熟悉的感觉,反正清爽多了。再就是一些快捷键绑定,ctrl+c ctrl+v等键全变了,唔,这不爽。还好,可以自定义.vimperatorrc修改键绑定。同vim一样,vimperator也内置了强大的帮助,即:help,该有的options里面貌似都有了。

进入vimperator的ff之后,执行命令:mkv将当前vimperator的配置保存到$HOME/.vimperatorrc里,然后就可以diy了。参考大牛的配置,修改了个简化版如下:

" 先把麻烦的东西拿掉
map A <nop>
map <c-q> <nop>
map <c-o> <nop>
map <c-i> <nop>
map <c-z> <nop>
map <c-p> <nop>
 
" show toolbar & scrollbar
set guioptions=Tr
 
" 前进后退
noremap q :back<cr>
noremap w :forward<cr>
 
" search
noremap <c-f> /
 
" close tab
noremap c :q<cr>
 
" F5
noremap <f5> :reload<cr>
 
" 解决全选、复制、粘帖、剪切和撤销与vimperator冲突的问题
noremap <c-V> <c-v>
noremap <c-Z> <c-z>
noremap <c-c> <c-v><c-c>
noremap <c-a> <c-v><c-a>
cnoremap <c-c> <c-v><c-c>
cnoremap <c-v> <c-v><c-v>
cnoremap <c-x> <c-v><c-x>
inoremap <c-a> <c-v><c-a>
inoremap <c-c> <c-v><c-c>
inoremap <c-v> <c-v><c-v>
inoremap <c-x> <c-v><c-x>
inoremap <c-z> <c-v><c-z>
inoremap <c-y> <c-v><c-y>
 
 
set titlestring=Mozilla Firefox
 
" 齐全的next和previous……
set nextpattern=\s*下一页|下一张|下一篇|下一????下页|后页\s*,^\bnext\b,\bnext\b,\bsuivant\b,^>$,^(>>|??????|??)$,^(>|??),(>|??)$,\bmore\b
set previouspattern=\s*上一页|上一张|上一篇|上一????上页|前页\s*,^\bprev|previous\b, \bprev|previous\b,\bprécédent\b,^<$,^(<<|??????|??)$,^(<|??),(<|??)$
 
" PassThrough gmail and greader
autocmd LocationChange .* js modes.passAllKeys = /.*(mail\.google\.com|www\.google\.com\/reader).*/.test(buffer.URL)
 
" Commands
" noimg可以减少流量,nojs用于调控一些不听话的网页
command noimg set! permissions.default.image=2
command ysimg set! permissions.default.image=1
command nojs set! javascript.enabled=false
command ysjs set! javascript.enabled=true

虽然痛恨配置,不过确实也是一劳永逸的东西。只要快捷键不要冲突,vimperator里设置的这些键还是很顺手的。看文档说貌似还可以用javascript扩展vimperator命令,想起来mozilla官方搞的那个Ubiquity,感觉两个东西貌似有点像!或许vimperator还要更强大些? :p

break the wall!

Posted on 七月 15th, 2009 in 杂碎 | 12 Comments »

灵感来自HelloTee的这件shirt,不知道现在还能不能买到 :D

用的< canvas>,所以ie下肯定是看不到了。源码不到一百行,见这里 ,稍微蛋疼了点 :p