YounG for You

don't be only father of your children

如果黑 请用力

| Comments

昨个和今天粗读了一下备受推崇的《Don’t make me think 》,虽然咱主力工作是后端攻城狮,但个人对前端技术还是非常感兴趣。

怀着无比崇敬的心情颤抖着翻开这份Web设计宝典,幻想着自己翻完此书即可向前端设计领域迈进一步。 事实证明我

读完本宝典最大的心得是:读书是一件愉快的事,如果你愿意深入字里行间,而不是匆匆扫描,你会发觉书籍通常会详细的还原人类认知和思考世界的大部分过程。换句话说:就是很多人们认为理所当然的事情会不假思索的去做,但这种不假思索其实也积累了人们思考和认知的多个步骤。不假思索的同时会意味这你忽略了其中的一些思考过程,通常也会忽略一些潜在的问题。

比如本书在第2章诠释的“我们实际上是如何使用Web的”指出:

第一个事实:我们不是阅读,而是扫描

现今的海量信息催使我们不得不加快节奏,阅读变成扫描,阅读之后甚至连理解消化的步骤都被自动省去。这一行为有些是主动, 比如对所读内容根本提不起兴趣,左眼进右眼出。 还有些是被动的,比如突然冒出一些打折或八卦消息,你就会马上转移注意力。 Twitter这种Web应用的出现更是引爆信息的广泛传播,助长了扫描的恶习。前一秒你还在为某高架桥坍塌事故遇害者点蜡烛, 眼泪还未挤出,没承想下一刻就爆出某公子艳照门。于是你赶紧撸鼻涕为力量,使劲浑身解数搜索,各大论坛,知道,搜搜, 问问都出现你跪求高清无码种子的销魂背影。 待到为依撸得人憔悴之时,蓦然回首发现扔在卫生纸下面的蜡烛,不免黯然神伤,心道:还是把它留到世界末日那天再为我粉身碎骨吧。 无论是twitter还是中国的微博,火爆起来的原因似乎都是因为人类偷窥的基因作祟。尤其是微博上, 有人现,有人捧场,有人吐槽。有人无节操现,有人无节操捧,吐槽者更无须节操。慢慢的,吐槽似乎变成某些人的爱好, 逞口舌之快诋毁众生,众生却依然乐在其中。最近微博上火爆的@留几手 大哥就是吐槽神人,为何神? 因为大哥的粉丝们以被他骂为荣,趋之若鹜。哪天被大哥的唾沫临幸了,恨不得奔走相告,转发给全世界。此为畸形文化。 无责任,无鸭梨,陋习肆意蔓延也就不足为怪。(请诸位勿要和政治联系,仅谈微博现象
这里还想跟各位做个绿色调查,程序猿是众所周知吐槽最严重的群体,因为这些人大多自负。请问其他行业这种现象明显么?
我从去年开始也沉迷于Twitter,每天工作闲暇就盯着Timeline刷新,乐在其中。自从看到以和菜头为代表的一批人宣布退出微博,退出Twitter。自己也开始思索碎片时间的利用,到底为什么人们对Twitter,微博这类产品这么着魔???
以下仅以中国用户举例分析:
前面提到的国民热衷偷窥应该是非常重要的诱导因素,可这还远远不够把用户牢牢拴在这2样产品上,达到每天不刷就心痒痒的程度。 不妨从另一个角度考虑,用户厌倦什么类型的应用?
* 长久不更新
* 更新无诚意
* 诚意无创意
* 创意不八卦
我这里斗胆揣测一下:大众娱乐的本质就是八卦
再反观Twitter和微博:
时时在更新,八卦乱轰炸!
尽管用户的兴趣点各有不同,但是用户自己会开启自动查找模式,完美匹配自己的兴趣点,即所谓的物以类聚,人以群分。轮番轰炸完全刺激到用户的G点,一波高潮刚消散,又一波高潮顶上来。同时用户零成本或低成本的接受或散播无营养信息,因为无须负责,病毒式传播在所难免。这种巧妙利用人性特点的产品实在是叫人赞不绝口。
说到这又想起了现在电商的促销手段。高级点的科学运用大数据分析,合理为用户推送优惠信息,并以发送垃圾消息为耻。 低级点的就是狂轰滥炸,甭管你需不需要,甭管我的促销是否真优惠,老子就是刺激你的G点,提醒你我这时不时的搞优惠活动。等用户真有购买需要的时候,大多数确实落入这个圈套,会将这种电商首先纳入考虑范围。于是人家也间接成功了,美其名曰:“暴力美学”。
扯得有点远,八卦呈泛滥之势,节操无限降低。如果无节操的生活成为主流节奏,恐怕将实践“谎话重复千遍即变真理”的悲哀。

再比如第4章 “为什么用户喜欢无须思考的选择”,

(可否)一句话概括 – 懒惰是人类的天性

后面几章的内容似乎对中国读者没什么用途,不推荐阅读。 比如“可用性是基本礼貌”,拿某连市公积金管理网站为例,政府项目只支持IE,其他浏览器上界面就乱七八糟。 还有一致命口诀: 欲用此站,必下插件;若已下载,未必成功; 多少仁人志士一口鲜血扑在显示器上。

末了,实在不觉得这本书是为Web从业人员编写的,应该面向的对象是那种技术白和那种特别傻的外国人。怀着忐忑的心情到读书圣地-豆瓣去拜读一下评论和打分,尼玛!打分居然是8.6!向打3星以下的读者表示敬意,打4,5星的读者悄悄献上一句“傻逼”,不留一丝遗憾。哦,差点忘了我看这本书是源于一个推上看到的书评,当时控制自己先看书再看书评,现在发现白控制了,这TM哪是书评,明明是把目录抄了一遍!哦,也许这位大侠也顿悟了,学习这本书最好的方法就是看一遍目录。 一本风靡网络,赞誉满满的好书在我这里坠落了。消耗了我一天半时间(刨除圣诞提前3小时下班,数小时刷推扯淡,应剩余4-5小时),收获的只是失望的书真的值得黑一下。请记得,

如果黑,请用力

后记:一不小心语无伦次扯了这么长的蛋,上面虽然不小心将Twitter和微博并列举例,但本人还是偏袒Twitter。 (理由你们懂的)
不过世界变化快,也许不久我再看自己这东西都觉得脑残,但没关系,那是我自己的事。想黑我的朋友请参考上面的大字,因为我的节操也所剩无几了。
最后想提下有一些人很早已经意识到信息乱流的弊端,并着手设计对策。比如阅读方面,由@Sunng 带头开发的美味爱读 www.readwise.net 就是非常好的尝试,大家自有自己的火眼金睛去评判,我就不多费口舌了。谨在此向 @Sunng 为代表的大神们致以我个人的敬意。

如何制作自己的gem (二)

| Comments

接上篇,如何制作自己的GEM (一)

写测试

泰斯特你的gem是贼拉的重要!它不仅帮助你确认你的代码是可以运行的,而且它也帮助别人了解你的gem是顺利工作的。当衡量一个gem时,ruby开发者倾向于通过查看一套可靠的测试(或者说由于缺少测试)来作为信任这段代码的主要理由。

Gems支持在代码包里添加测试文件,所以当下载完gem后我们就可以开始测湿了。有一个致力于此的社区已经出现,它的名字叫GemTesters,这里有详细的文档介绍在不同的Ruby架构和解释器中运行gem测湿。

一句话不割:请测试你的GEM!

Test::Unit是Ruby内置的测湿框架。网上狼哇多的教程介绍如何使用它。当然还有许多其他的测试框架可用。Rspec是很流行的一个。说白了,不管你用哪个,测湿就行!

下面咱们给女神加点测湿。需要再加几个文件:一个是Rakefile,还有一个全新的test文件夹:

1
2
3
4
5
6
7
8
9
10
11
12
% tree
.
├── Rakefile
├── bin
│   └── nvshen
├── nvshen.gemspec
├── lib
│   ├── nvshen
│   │   └── translator.rb
│   └── nvshen.rb
└── test
    └── test_nvshen.rb

Rakefile可以让你自动跑测湿:

1
2
3
4
5
6
7
8
9
% cat Rakefile
require 'rake/testtask'

Rake::TestTask.new do |t|
  t.libs << 'test'
end

desc "Run tests"
task :default => :test

现在执行rake test或者就rake就能跑测湿啦。呵呵,下面是一个女神的基本测湿文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
% cat test/test_nvshen.rb
require 'test/unit'
require 'nvshen'

class NvshenTest < Test::Unit::TestCase
  def test_english_hello
    assert_equal "hello nvshen",
      nvshen.hi("english")
  end

  def test_any_hello
    assert_equal "hello nvshen",
      nvshen.hi("ruby")
  end

  def test_spanish_hello
    assert_equal "你好 女神",
      nvshen.hi("chinese")
  end
end

最后执行测湿:

1
2
3
4
5
6
7
8
9
10
% rake test
(in /Users/qrush/Dev/ruby/nvshen)
Loaded suite
Started
...
Finished in 0.000736 seconds.

3 tests, 3 assertions, 0 failures, 0 errors, 0 skips

Test run options: --seed 15331

绿灯通过!好吧,其实取决与你的shell配色。想学习更多的好例子,最佳实践就是去github瞎溜达并且读别人的代码。


给代码写文档

大多数gems默认用RDoc来生成文档。有大量好的教程传授如何用RDoc来写文档。下面是一个简单示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# The main Nvshen driver
class Nvshen
  # Say hi to the world!
  #
  # Example:
  #   >> Nvshen.hi("chinese")
  #   => 你好 女神
  #
  # Arguments:
  #   language: (String)

  def self.hi(language = "english")
    translator = Translator.new(language)
    puts translator.hi
  end
end

另一个出色的文档选择是YARD,因为当你推送gem时,RubyDoc.info会通过你的gem自动生成YARDocs。 YARD向后兼容RDoc,并且有一篇文章很好的文章介绍了他们的区别以及用法。


总结

有了一个构建RubyGem的基本思路,我们希望你将去亲自实践。


演员表

这篇教程借鉴了Gem Sawyer的Modern Day Ruby Warrior,由Jerry Huo翻译改编。如有巧合,纯属雷同!

【翻译】如何制作自己的GEM (一)

| Comments

原文链接: 猛击这里

今天这个会,我们将学习如何把你的ruby代码打包成外卖(pia!开会开出瘾了?外卖个头,你个吃货! 是gem啊!)


介绍

感谢RubyGems内嵌的一个工具,让我们创建和发布gem变得非常简单。下面我们来制作一个简单的“hello 女神”gem,大家回家以后可以随便耍耍! 我们要做的这个gem的代码已经在github安家了,需要的猛击。


处女gem

我将从一个ruby文件开始来创建这个女神gem,还有她的闺蜜gemspec。你愿意的话可以给这个gem起个新名字来发布(或许是波多野结衣神马的,你懂的)。查阅并参考一下官方样式向导的基本推荐来命名你的Gem。

1
2
3
4
5
% tree
.
├── nvshen.gemspec
└── lib
    └── nvshen.rb

Gem的代码主要放置在lib目录下。通常的原则是让一个ruby文件和你的gem名字相同,因为当require 'nvshen'运行时,她会自动被加载。她的闺蜜文件是负责设置你的gem代码和API。

lib/nvshen.rb里的代码是非常柔弱无骨的。它只是保证你可以看到女神gem会有些输出:

1
2
3
4
5
6
% cat lib/nvshen.rb
class Nvshen
  def self.hi
    puts "Hello Nvshen!"
  end
end

gemspec文件定义了gem的内容,作者,还有gem的版本。它也是你通往RubyGems.org的介绍信。你在一个gem上所能看到的所有信息(象jekyll)都来自这个闺蜜文件-gemspec。

1
2
3
4
5
6
7
8
9
10
11
12
13
% cat hola.gemspec
Gem::Specification.new do |s|
  s.name        = 'nvshen'
  s.version     = '0.0.0'
  s.date        = '2012-12-29'
  s.summary     = "Nvshen!"
  s.description = "A simple hello nvshen gem"
  s.authors     = ["Jerry Huo"]
  s.email       = 'hjzdhr@163.com'
  s.files       = ["lib/nvshen.rb"]
  s.homepage    =
    'http://rubygems.org/gems/hola'
end

脸熟吧?这个闺蜜gemspec也是ruby系的,所以你可以写脚本来生成文件名和更改版本号。这个闺蜜妹子还有很多内置参数,感兴趣的请猛击这里

当你创建完这个gemspec文件后,你就可以通过它构建一个gem了。然后在本地安装这个gem来进行测试。

1
2
3
4
5
6
7
8
9
% gem build nvshen.gemspec
Successfully built RubyGem
Name: nvshen
Version: 0.0.0
File: nvshen-0.0.0.gem

% gem install ./nvshen-0.0.0.gem
Successfully installed nvshen-0.0.0
1 gem installed

这个迷烟测试还没有结束:最后一步就是require此gem并调戏她:

1
2
3
4
5
% irb
>> require 'nvshen'
=> true
>> Nvshen.hi
Hello Nvshen!

如果你使用的ruby版本低于1.9.2,你需要使用irb -rubygems,或者运行irb之后再require rubygems库

现在你可以和ruby社区的其他人一起分享女神这个gem。假设你已经有了一个账户, 把你的gem发布到RubyGems.org只需要一个命令。按下面提示在你的电脑上设置你的RubyGems账户:

1
2
3
$ curl -u YOUR_USER_NAME https://rubygems.org/api/v1/api_key.yaml >
~/.gem/credentials
Enter host password for user 'YOUR_USER_NAME':

设好这一步,你就可以推出你的新Gem了:

1
2
3
% gem push nvshen-0.0.0.gem
Pushing gem to RubyGems.org...
Successfully registered gem: nvshen (0.0.0)

很短的时间之内(通常不超过一年),任何人都可以安装你的gem了。你可以在RubyGems.org上看到她,或者通过RubyGems.org上在任何计算机上得到她。

1
2
3
4
5
6
7
8
9
% gem list -r nvshen

*** REMOTE GEMS ***

nvshen (0.0.0)

% gem install nvshen
Successfully installed nvshen-0.0.0
1 gem installed

用Ruby和RubyGems分享代码实在是太轻松了。


包含更多文件

把所有东西放在一个文件里会影响扩展。我们再让女神丰满点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
% cat lib/nvshen.rb
class Nvshen
  def self.hi(language = "english")
    translator = Translator.new(language)
    puts translator.hi
  end
end

class Nvshen::Translator
  def initialize(language)
    @language = language
  end

  def hi
    case @language
    when "chinese"
      "你好 女神"
    else
      "hello nvshen"
    end
  end
end

女神变得有点臃肿。让我们把Translator分解成单独的文件。如前面提到的,gem根目录那个文件是负责加载gem的代码。gem的其他文件通常放置在lib文件夹下与gem同名的目录底下。我们可以把这个gem分解成这样:

1
2
3
4
5
6
7
% tree
.
├── nvshen.gemspec
└── lib
    ├── nvshen
    │   └── translator.rb
    └── nvshen.rb

Translator现在位于lib/nvshen目录下,我们可以通过require方式在lib/nvshen.rb里轻松的调用它。Translator的代码并没有多大差异:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
% cat lib/nvshen/translator.rb
class Nvshen::Translator
  def initialize(language)
    @language = language
  end

  def hi
    case @language
    when :chinese
      "你好 女神"
    else
      "hello nvshen"
    end
  end
end

但现在nvshen.rb里需要增加一点代码来加载Translator:

1
2
3
4
5
6
7
8
9
% cat lib/nvshen.rb
class Nvshen
  def self.hi(language = :english)
    translator = Translator.new(language)
    translator.hi
  end
end

require 'nvshen/translator'

接下来试一试,启动irb

1
2
3
4
5
% irb -Ilib -rnvshen
irb(main):001:0> Nvshen.hi(:english)
=> "hello nvshen"
irb(main):002:0> nvshen.hi(:chinese)
=> "你好 女神"

这里我们需要用到一个奇怪的命令行标志-Ilib. 通常RubyGems会自动替你引用lib目录,所以终端用户通常不需要为配置加载路径而担忧。 然而,如果你是在RubyGems之外的环境运行代码,你就需要自己配置这些东西。可能有人会在代码里操作$LOAD_PATH,但那通常被视为反面示范。在这个向导里有很多反面示例(当然也有正面示例)。

如果你在gem里添加了许多文件,千万要记得在发布前把他们加到gemspec的file数组里。因此,许多开发者通过Hoe, Jeweler, Rake, Bundler 来自动化此步骤,或者直接使用动态gemspec。

从这开始,再通过添加更多代码来增加更多目录都是相同的步骤。尽可能合理的分割ruby文件。使你的项目井然有序将帮助你自己和未来的维护者减少头疼和麻烦。


添加可执行文件

Gem除了可以提供ruby代码的库,还可以曝光一个或多个可执行文件到shell的PATH上。可能最知名的例子就是rake了。另一个非常有用的是prettify_json.rb, 包含在JSON的gem里。 它可以把JSON格式化成更可读的形式(ruby1.9众也内置了它)。例子如下:

1
2
3
4
5
% curl -s http://jsonip.com/ | \
  prettify_json.rb
{
  "ip": "24.60.248.134"
}

给gem添加可执行文件的步骤非常简单。你只需要把那个文件放在gem的bin目录底下,然后把它加到gemspec的可执行文件的列表里。咱们来给女神gem添加一个。第一步创建文件并让她可以执行:

1
2
3
% mkdir bin
% touch bin/hola
% chmod a+x bin/hola

可执行文件本身需要一个[shebang](http://www.catb.org/jargon/html/S/shebang.html)来制定是运行什么程序。下面的女神的文件示例:

1
2
3
4
5
% cat bin/nvshen
#!/usr/bin/env ruby

require 'nvshen'
puts Nvshen.hi(ARGV[0])

她的作用就是加载女神gem,然后把命令行第一个参数作为语言的变量来输出结果。下面是运行示例:

1
2
3
4
5
% ruby -Ilib ./bin/hola
hello nvshen

% ruby -Ilib ./bin/hola chinese
你好 女神

最后,为了使你发布gem的时候,可执行文件被包括其中,你需要把它加到gemspec中:

1
2
3
4
5
% head -4 nvshen.gemspec
Gem::Specification.new do |s|
  s.name        = 'nvshen'
  s.version     = '0.0.1'
  s.executables << 'nvshen'

推送新gem,你就可以发布自己的命令行工具。需要的话,你可以添加更多的可执行文件,记得也把他们加到gemspec里面的executables的数组。

注意:你推送一个新发布时,需要加上新的版本号,更多有关Gem版本的资料,请猛击Pattern Guide

未完待续(稍后更新测试)

CSV Rendered by Fputcsv Does Not Separated Correctly

| Comments

Recently I am working on a feature which exports the data presented on the web page to a csv file. That’s pretty easy, huh? The only trouble is the web site was built with Yii Framework

Luckily, I found there’s already an light-weight extention called csvexport and you can find it here http://www.yiiframework.com/extension/csvexport

The usage example is pretty clear:

1
2
3
4
5
6
7
8
 Yii::import('ext.ECSVExport');
 // CDbCommand
 $cmd = Yii::app()->db->createCommand("SELECT * FROM track_test LIMIT 10");    
 $csv = new ECSVExport($cmd);       
 $exclude = array('id', 'deleted', 'prefix');
 $csv->setExclude($exclude);
 $csv->setOutputFile($outputFile);
 $content = $csv->toCSV();

if you would like to download csv from browser instead of writing to a file, add this line:

1
2
 Yii::app()->getRequest()->sendFile('export.csv', $content, "text/csv", false);
 exit;

Everything goes well so far. But when I open the new csv file with Excel 2008 (Mac), I found there’s a problem for human reading, because all data (more than 10 columns) are crowded in the first column, not separated by comma at all!!!

I checked the csv file carefully by opening it with textmate and found it’s rendering correctly, although not all data have the double quote enclosure. It does not effect the result.

The “csvexport” lib is using fputcsv to render csv.

1
 fputcsv($this->_filePointer, $headers, $this->_delimiter, $this->_enclosure);

The default delimiter is comma - “,” how about changing it to another one? Let’s try semicolon, Oops!!! It’s working great now.

1
 fputcsv($this->_filePointer, $headers, ";", $this->_enclosure);

Is it a Microsoft Office bug or php bug? Let me know your idea!

Fsockopen Error - Failed to Parse Address

| Comments

Just met this error when using MailPress plugin in WordPress. on file

"wp-content/plugins/mailpress/mp-includes/Swiftmailer/classes/Swift/Transport/StreamBuffer.php" Line 233

    if (!$this->_stream = fsockopen($host, $this->_params['port'], $errno, $errstr, $timeout))
    {
      throw new Swift_TransportException(
        'Connection could not be established with host ' . $this->_params['host'] .
        ' [' . $errstr . ' #' . $errno . ']'
        );
    }

Checked the php manual: fsockopen It says

1
resource fsockopen ( string $hostname [, int $port = -1 [, int &$errno [, string &$errstr [, float $timeout = ini_get("default_socket_timeout") ]]]] )

After some research, I found that we can’t leave the port parameter empty, although it is stated optional.

This can be traced to C function “parse_ip_address_ex”, it needs a colon to separate IP and port number in the textual address it is passed.

Refer from this topic

So the solution is simple, either add a port behind the server’s address, or specify a port as the second parameter.

Simple Solution
1
2
3
fsockopen('relay.xxx.com:25');
or
fsockopen('relay.xxx.com', 25);

Of course we won’t change the MailPress’s source code, just change the MailPress settings on the dashboard :)

First Post

| Comments

Hello Octopress! This an example post for more information see: