<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>湖间小筑</title>
	
	<link>http://www.hzmangel.info/blog</link>
	<description>蓝天，小湖，湖水中一方小筑</description>
	<lastBuildDate>Fri, 11 May 2012 06:22:38 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/hzmangel" /><feedburner:info uri="hzmangel" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Deploy RoR application with Nginx</title>
		<link>http://feedproxy.google.com/~r/hzmangel/~3/NncYJUD15tU/1133</link>
		<comments>http://www.hzmangel.info/blog/archives/1133#comments</comments>
		<pubDate>Fri, 11 May 2012 03:40:52 +0000</pubDate>
		<dc:creator>hzmangel</dc:creator>
				<category><![CDATA[Happy coding]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[tools]]></category>

		<guid isPermaLink="false">http://www.hzmangel.info/blog/?p=1133</guid>
		<description><![CDATA[This article will talk something about deploying RoR application to local and remote nginx server. Deploy RoR on local machine Like deploying other website, the static file is served via nginx, and the Ruby logic will be handled via some &#8230; <a href="http://www.hzmangel.info/blog/archives/1133">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This article will talk something about deploying RoR application to local and remote nginx server.<br />
<span id="more-1133"></span></p>
<h3>Deploy RoR on local machine</h3>
<p>Like deploying other website, the static file is served via nginx, and the Ruby logic will be handled via some middle-wares, here is the list:</p>
<h4>Thin</h4>
<ol>
<li>
<p>Install the <code>thin</code> via <code>homebrew</code></p>
<pre class="brush: bash"> gem install thin
</pre>
</li>
<li>
<p>Start the thin server. Since this is a testing deploy, I just execute thin in the project directory.</p>
<pre class="brush: bash"> thin start
</pre>
<p> After the command executed, you can find some information printed via <code>thin</code> command. The default port of the server is <em>3000</em>, which should be used to fill the nginx configuration file.</p>
</li>
<li>
<p>Update the configuration file for nginx. The <code>upstream</code> section should be put in <code>http</code> block.</p>
<pre class="brush: bash"> upstream todo_app {
     server http://127.0.0.1:3000
 }
</pre>
<p> The <code>location</code> section should be put in <code>server</code> block.</p>
<pre class="brush: bash"> location / {
     proxy_set_header  X-Real-IP  $remote_addr;
     proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
     proxy_set_header  Host $http_host;
     proxy_redirect    off;

     try_files $uri $uri/index.html $uri.html @ruby;
 }

 location @ruby {
     proxy_pass http://todo_app
 }
</pre>
<p> The <code>proxy_pass</code> will pass all ruby request to the upstream server. <code>Unix socket</code> can also be used in the <code>upstream</code> section.</p>
</li>
<li>
<p>Restart the nginx server, the RoR project can be shown in the web browser now.</p>
</li>
</ol>
<h4>Passenger</h4>
<ol>
<li>
<p>Install passenger via gem</p>
<pre class="brush: bash"> gem install passenger
</pre>
</li>
<li>
<p>Install passenger module for nginx</p>
<pre class="brush: bash"> passenger-install-nginx-module
</pre>
<p> Or you can install nginx and passenger module with brew like this</p>
<pre class="brush: bash"> brew install nginx --with-passenger
</pre>
<p> If nginx still report the error that can not find the <code>PassengerLoggingAgent</code>, try to use <code>passenger package-runtime</code> and then get the agent from package <code>passenger-standalone/XXX/support.tar.gz</code></p>
<p> In the <em>http</em> section, you should specify the value of <code>passenger_root</code> and <code>passenger_ruby</code>. Here is the configuration in my laptop:</p>
<pre class="brush: bash"> passenger_root /usr/local/lib/ruby/gems/1.9.1/gems/passenger-3.0.12;
 passenger_ruby /usr/local/bin/ruby;
</pre>
<p> <strong>NOTICE:</strong> Make sure to set <code>rails_env</code> variable is set to the same stage with development, seems the default value is <code>production</code>. Here is my configuration section in nginx:</p>
<pre class="brush: bash"> passenger_root /usr/local/lib/ruby/gems/1.9.1/gems/passenger-3.0.12;
 passenger_ruby /usr/local/bin/ruby;

 server {
     listen       8080;
     server_name  localhost;
     root /Users/ziming/tmp/learn_rb/rails/todo_app/public;
     passenger_enabled on;
     rails_env development;
 }
</pre>
</li>
</ol>
<h4>Unicorn</h4>
<ol>
<li>
<p>Install unicorn via gem</p>
<pre class="brush: bash"> gem install unicorn
</pre>
</li>
<li>
<p>Get the sample configuration file from unicorn website</p>
<pre class="brush: bash"> curl -o config/unicorn.rb https://raw.github.com/defunkt/unicorn/master/examples/unicorn.conf.rb
</pre>
<p>And update the <code>working_directory</code>, <code>pid</code>, <code>stderr_path</code> and <code>stdout_path</code> in the sample configuration file.<br />
<strong>NOTICE</strong>: Need absolute path here.</p>
</li>
<li>
<p>The left step is the same with Thin, a <code>upstream</code> section should be added to nginx.conf, and redirection should be added to <code>location</code> section.</p>
</li>
</ol>
<h3>Deploy remotely via Capistrano</h3>
<p>Capistrano is a useful tool for deploying RoR application to remote server(s). The Capistrany package provides several tasks for simplfying the deploying jobs.</p>
<ol>
<li>
<p>Prepare the RoR application</p>
<p> Before deploying, we should prepare the application. Since this only show how to deploy, so we just use the generated project. I have create a repository on bitbucket, and the scm used for this application is mercurial.</p>
<p> First I create the repository DailyCheckIn on butbucket, then I clone the project to local directory <code>dailycheckin</code>. The directory is an empty directory except some mercurial information. After directory ready, I create RoR application via <code>rails new</code><br />
command. Before doing the initialization commit, I should create a <code>.hgignore</code> file based on the <code>.gitignore</code> (Just add <code>syntax: glob</code> at the first line, remove the leader slash in the path, and rename <code>.gitignore</code> to <code>.hgignore</code>). After all things done, commit the new added file and push to the server, then we have a RoR application.</p>
</li>
<li>
<p>Capify the RoR project</p>
<p> The project should be &lsquo;capified&rsquo; before deplying via Captistrano, which can be done via command <code>capify .</code> easily. This command will create <code>Capfile</code> and <code>config/deploy.rb</code> file in current directory. The <code>Capfile</code> is the wrapper, and the tasks is written in file <code>deploy.rb</code></p>
</li>
<li>
<p>Configure the Capistrano</p>
<p> Here are the information should be checked before deploying:</p>
<ul>
<li>Application name</li>
<li>Server information
<ul>
<li>Application layer</li>
<li>Wer server</li>
<li>Database</li>
</ul>
</li>
<li>SCM information
<ul>
<li>Repository location</li>
<li>SCM type</li>
</ul>
</li>
<li>Directory the project should be deployed to</li>
</ul>
<p>Here is a sample configuration file for the project</p>
<pre class="brush: text">
set :application, "DailyCheckIn"
set :repository,  <Repo>
set :scm, :mercurial
server <server>, :web, :app, :db, :primary => true
set :deploy_to, <Deploy path>
set :use_sudo, false
</pre>
<p> The detailed information of configuration can be found in <a href="https://github.com/capistrano/capistrano/wiki/2.x-From-The-Beginning" title="Capistrano document">Capistrano document</a>.</p>
</li>
<li>
<p>Deploy the application</p>
<p> Next step is deploy the application. The first step is setting up the server, Capistrano provide task <code>cap deploy:setup</code> to do this. This task will do a series of <code>mkdir</code> calls. Make sure the permission of directory.</p>
<p> After setting up completed,  it is recommended to check the dependencies via <code>cap deploy:check</code> command. Re-run this command after any change to the environment to make sure all check passed.</p>
<p> The next step should be done manually, you should login to the server and make sure the database can meet the requirement configured in the <code>config/database.yml</code> file.</p>
<p> After environment ready, task <code>deploy:update</code> can be used to clone the code to server. The clone operation will create a new snapshot in the <code>releases</code> directory, and link it with symbol link <code>current</code> in top level of depoly directory. Then <code>cap deploy:start</code> can be used to start the services.</p>
</li>
</ol>

<p><a href="http://feedads.g.doubleclick.net/~a/8L-rtaXAiSmnztFJ4NHoR_5crqk/0/da"><img src="http://feedads.g.doubleclick.net/~a/8L-rtaXAiSmnztFJ4NHoR_5crqk/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/8L-rtaXAiSmnztFJ4NHoR_5crqk/1/da"><img src="http://feedads.g.doubleclick.net/~a/8L-rtaXAiSmnztFJ4NHoR_5crqk/1/di" border="0" ismap="true"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.hzmangel.info/blog/archives/1133/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.hzmangel.info/blog/archives/1133</feedburner:origLink></item>
		<item>
		<title>RoR learning log (2)</title>
		<link>http://feedproxy.google.com/~r/hzmangel/~3/oJjeZNpt66Y/1125</link>
		<comments>http://www.hzmangel.info/blog/archives/1125#comments</comments>
		<pubDate>Mon, 07 May 2012 15:57:16 +0000</pubDate>
		<dc:creator>hzmangel</dc:creator>
				<category><![CDATA[Happy coding]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.hzmangel.info/blog/?p=1125</guid>
		<description><![CDATA[This article will finish the ToDo web application, and the prime area in this article is adding validator and updating templates. Here is to RoR learning log (1) According to the requirements, the length of ToDo account should less than &#8230; <a href="http://www.hzmangel.info/blog/archives/1125">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This article will finish the ToDo web application, and the prime area in this article is adding validator and updating templates.</p>
<p>Here is <a href="http://www.hzmangel.info/blog/archives/1113" title="RoR learning log (1)" target="_blank">to RoR learning log (1)</a></p>
<p><span id="more-1125"></span></p>
<p>According to the requirements, the length of ToDo account should less than 100 characters and the status of ToDo can only be chosen from 0 or 1, so some validator should be added to the model. With the validator, the model code should be looked like:</p>
<pre class="brush: ruby">
STATUS_OPTION = [0, 1]

class ToDo < ActiveRecord::Base
  attr_accessible :content, :status
  validates :content, :presence => true,
                      :length => { maximum: 100 }
  validates :status, :presence => true,
                     :numericality => { :only_integer => true },
                     :inclusion => { :in => STATUS_OPTION }
end
</pre>
<p>Statements started with `validates` keyword are validator. The available condition list can be checked at <a href="http://guides.rubyonrails.org/active_record_validations_callbacks.html">this page</a>. If the value passed in break the rule, the error message will be shown in the page.</p>
<p>With the validators, the value saved can be guaranteed to be correct. But seems radio box or drop down box is better than the text field, so we plan to modify the template page. The template is placed under `app/views/to_dos` directory, which is a HTML file with some template control commands. By default, when viewing the URL http://[address]/index, the template with the same name, index.html.erb, will be rendered. The generated form is saved in file `_form.html.erb`, the default type of status is `number_field`, which should be updated to `select`. The document for `select` is <a href="http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#M001593">here</a>, according the document, the option list should be provided, and here we can use the constant `STATUS_OPTION` defined in model file. Here is the updated `status` field in the form object: </p>
<pre class="brush: html">
<div class="field">
  <%= f.label :status %>
  <%= f.select :status, ToDo::STATUS_OPTION %>
</div>
</pre>
<p>The form type will change from text field to drop down menu after updating the form.</p>
<p>Congratulations, a simple ToDo application has been worked out. It is a very simple application, which do not contain the static files, user authentication, unit test and so on. In next step, I plan to re-write the <a href="http://www.linuxfb.org">linuxfb</a> website with more better structure, hope can touch more features in RoR.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/hlUMsashiOjBnx1MX61r9oNCnpI/0/da"><img src="http://feedads.g.doubleclick.net/~a/hlUMsashiOjBnx1MX61r9oNCnpI/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/hlUMsashiOjBnx1MX61r9oNCnpI/1/da"><img src="http://feedads.g.doubleclick.net/~a/hlUMsashiOjBnx1MX61r9oNCnpI/1/di" border="0" ismap="true"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.hzmangel.info/blog/archives/1125/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.hzmangel.info/blog/archives/1125</feedburner:origLink></item>
		<item>
		<title>RoR learning log (1)</title>
		<link>http://feedproxy.google.com/~r/hzmangel/~3/UjV-eyrqlqg/1113</link>
		<comments>http://www.hzmangel.info/blog/archives/1113#comments</comments>
		<pubDate>Sun, 06 May 2012 16:51:32 +0000</pubDate>
		<dc:creator>hzmangel</dc:creator>
				<category><![CDATA[Happy coding]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.hzmangel.info/blog/?p=1113</guid>
		<description><![CDATA[Just back from vacation, so the study log for this week is simple. Build development environment The whole process is tested on Mac OS, and I think this may have little difference with Linux. Ruby should be installed before trying &#8230; <a href="http://www.hzmangel.info/blog/archives/1113">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Just back from vacation, so the study log for this week is simple.<br />
<span id="more-1113"></span></p>
<h3>Build development environment</h3>
<p>The whole process is tested on Mac OS, and I think this may have little difference with Linux.</p>
<p>Ruby should be installed before trying Rails. To separate with the Ruby used by system, it is recommended to use RVM (Ruby version manager) to build the local Ruby environment (seems like the virtualenv in Python). Here is the install script from <a href="https://rvm.io//rvm/install/" title="RVM Install" target="_blank">RVM installing page</a></p>
<pre class="brush: bash">
$ curl -L get.rvm.io | bash -s stable
$ source ~/.rvm/scripts/rvm
$ rvm requirements
$ rvm install 1.9.3
</pre>
<p>After installing, the command <code>rvm use</code> can be used to select the version of Ruby.</p>
<p>Next per-requisite is gem, which can be get from <a href="http://rubyforge.org/frs/?group_id=126" target="_blank">this page</a> </p>
<p>Then we can use gem to install rails</p>
<pre class="brush: bash">
gem install rails
</pre>
<h3>A simple TODO list</h3>
<p>This section will implement a todo list application, which is copied from <a href="http://bottlepy.org/docs/dev/tutorial_app.html" target="_blank">bottle tutorial page</a>. Here is the goal copied from that page:</p>
<blockquote><p>
At the end of this tutorial, we will have a simple, web-based ToDo list. The list contains a text (with max 100 characters) and a status (0 for closed, 1 for open) for each item. Through the web-based user interface, open items can be view and edited and new items can be added.
</p></blockquote>
<p>This log only create the default controller, and some other thing such as adding validator and modifying template will be shown in next log.</p>
<p>First, we have to create the directory for application. We named the application to `todo_app`, and we run this command to do the initialization:</p>
<pre class="brush: bash">
$ rails new todo_app
</pre>
<p>After plenty of output message, we have a new directory named todo_app, and the directory structure has been initialized in it. After running `rails server` in the directory, we can access the default website via http://127.0.0.1:3000</p>
<p>Next step is generate database schema for this application. As mentioned above, the schema contains two fields, one is record content, the other is status of record. Rails provide a generator script to simplify the operation.</p>
<pre class="brush: bash">
$ rails generate scaffold ToDo content:string status:integer
</pre>
<p>Then use rake command to migrate the database</p>
<pre class="brush: bash">
$ rake db:migrate
</pre>
<p>This script will generate URL mapping, model and default view for the ToDo table. You can use http://127.0.0.1:3000/to_dos to access the new added things (You can check the config/routes.rb to find the correct mapping). There is no data currently, but there is a link to add new record, which is linked to http://127.0.0.1:3000/to_dos/new. And after record added, there will be show, edit and destroy action to each record.</p>
<p>The controller, view and model is saved in app directory. The file app/controllers/to_dos_controller.rb will handle the request sent from browser, the file app/models/to_do.rb is the model of ToDo record, and the files under app/views/to_dos/ will show the returned record. In this demo project, we need add some validation while adding ToDo record, and modify the list page for updating the ToDo record.</p>
<p>For now, there is a simple web application, can use generated view/controller/model to manager ToDo list. In the next log, this application will have a validator and new template.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/OVnirs_wE6Giii9fEOWtn0FQwi8/0/da"><img src="http://feedads.g.doubleclick.net/~a/OVnirs_wE6Giii9fEOWtn0FQwi8/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/OVnirs_wE6Giii9fEOWtn0FQwi8/1/da"><img src="http://feedads.g.doubleclick.net/~a/OVnirs_wE6Giii9fEOWtn0FQwi8/1/di" border="0" ismap="true"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.hzmangel.info/blog/archives/1113/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.hzmangel.info/blog/archives/1113</feedburner:origLink></item>
		<item>
		<title>Ruby learning log</title>
		<link>http://feedproxy.google.com/~r/hzmangel/~3/2-V8mIVR1Rs/1101</link>
		<comments>http://www.hzmangel.info/blog/archives/1101#comments</comments>
		<pubDate>Sat, 28 Apr 2012 03:34:51 +0000</pubDate>
		<dc:creator>hzmangel</dc:creator>
				<category><![CDATA[Happy coding]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.hzmangel.info/blog/?p=1101</guid>
		<description><![CDATA[Just studied Ruby with the tutorial on website rubylearning.com in the past week, and here are some knowledge gained those days. General Ruby is free format and case sensitive. Besides commenting one line code with leading #, Ruby can use &#8230; <a href="http://www.hzmangel.info/blog/archives/1101">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Just studied Ruby with the tutorial on website <a href="http://rubylearning.com/" target="_blank">rubylearning.com</a> in the past week, and here are some knowledge gained those days.<br />
<span id="more-1101"></span></p>
<h4>General</h4>
<ul>
<li>Ruby is free format and case sensitive.</li>
<li>Besides commenting one line code with leading #, Ruby can use `=being` and `=end` to define a comment block.</li>
<li>Everything in Ruby is object. Which means 1.5 means a float number but 1.times can generate a enumerator.</li>
<li>Ruby use `nil` to indicate a NULL object</li>
<li>Only `false` and `nil` is false. Be careful, you have to face the fact that `if 0` will do not enter else branch in Ruby, which is different with other language I have learned.</li>
<li>There is no `++` and `&#8211;` in Ruby, you can work around with `+=1` and `-=1` sometimes.</li>
<li>Constant name must start with capital letter, and local variable must start with lowercase letter or underscore(`_`). Program can not be executed if name do not obey this rule (hmm&#8230; Python use force indent, while Ruby use force name type).</li>
<li>In Ruby, constant, class and module are all treated as constant, so must follow the constant name rule.</li>
<li>Parentheses are optional while defining or calling function, so all the code following is legal:</li>
</ul>
<pre class="brush: ruby">foobar
foobar()</pre>
<pre class="brush: ruby">foobar(a, b, c)
foobar a, b, c</pre>
<pre class="brush: ruby">def foo bar
    puts bar
end

def foo(bar)
    puts bar
end</pre>
<ul>
<li>`.to_i`, `.to_f` and `.to_s` are used to convert object to integer, float and string.</li>
<li>You can insert underscore(_) in integer number to make it more readable.</li>
</ul>
<h4>Variable and method</h4>
<ul>
<li>Global, local, instance and class variable are defined in different way</li>
<li>Variable with prefix `$` means global variable</li>
<li>Variable with prefix `@` means instant variable in class, like `self.var` in Python</li>
<li>Variable with prefix `@@` means the class variable, like static variable in C++</li>
<li>Ruby also include some built in variable:</li>
<li>`$0` means the filename.</li>
<li>`$:` means search path, which is a list, like the `sys.path` in Python.</li>
<li>`$$` means the process id.</li>
<li>Usually, a variable can be assigned default value with this syntax: `var ||= `</li>
<li>Only `?`, `!` and `=` can be used as suffix to the method</li>
<li>method name ends with `?` means this method will return boolean value.</li>
<li>method name ends with `!` means this method will do changes on original object instead of creating new copy.</li>
<li>method name ends with `=` can used to define operator.</li>
<li>If no `return` at last of function, the value of last expression will be returned as return value.</li>
<li>Argument of method can be defined as `*args`, which means the method can accept uncertain number of argument.</li>
<li>Seems there is no `**args` in Ruby, arguments passed with `*args` will lost information of argument name. The `**args` used in Python method can accept argument with name.</li>
<li>`alias` can be used to define a alias for a method/operator/global var/regular expression back-ref, but not local var/class var/constant. The object pointed by new name will NOT updated after updating old one.</li>
</ul>
<h4>String</h4>
<ul>
<li>Ruby use `puts` to print string to screen, and `gets` to receive string from standard input.</li>
<li>`puts` is used like a keyword, but actually it is a method defined in Ruby kernel</li>
<li>`puts` method will invoke `to_s` method of an object</li>
<li>Strings fetched with `gets` will usually be tidied by `chomp` method</li>
<li>You can use `+` to connect string. Like Python, it will create a new string object, so the performance may downgrade if connecting too may string with `+`</li>
<li>String defined by single quota and double quota are different. A string defined by single quota only convert `\\` to `\`, which means `&#8217;a\\n&#8217;` == `&#8217;a\n&#8217;`, and all the three character will be printed out with `puts`. While the double quota will convert all escape string, further more, it will also handle the expression interpolation `#{}`.</li>
<li>There are three methods to compare string, `==`, `eql?` and `equal?`. The first two methods compare string content while the last one compares object id.</li>
<li>A magic keyword `%w` can be used to build string array, like this: %w{ab cd ef gh \n} == ["ab", "cd", "ef", "gh", "\\n"].</li>
</ul>
<h4>Flow control and code block</h4>
<ul>
<li>`if..else..end`, and the else if is written as `elsif` in Ruby. (hmm&#8230; we have `else if`, `elseif` and `elif` yet, and now we have `elsif`, seems we only need elf now).</li>
<li>There is reverse if, named `unless`, help to write complex logic?</li>
<li>There is `cond ? a : b` operator in Ruby.</li>
<li>There is a switch-case model in Ruby, `case..when..else..end`</li>
<li>Code blocks are defined in `{ }` (single line) or `do..end` (multiple line). The `{ }` has higher precedence than `do..end`.</li>
<li>Code block followed by function will be executed after `yield` called in the function.</li>
<li>Can pass argument to block by passing argument to `yield`.</li>
<li>Method `block_given?` can be used in function to check whether this function has block followed.</li>
</ul>
<h4>Array, range and hash</h4>
<ul>
<li>Seems there is no index error in Ruby, you will get `nil` if try to access element out of array size.</li>
<li>`ARGV` means command line arguments, which is an array.</li>
<li>Range can be generated via `a..b` or `a&#8230;b`, the list generated with three dots do not contain `b`.</li>
<li>`.to_a` method can convert a range object to array.</li>
<li>There is a `===` operator in range object, check whether the element is included in range.</li>
<li>Name start with `:` is a symbol, which is unique in global.</li>
<li>There is a symbol table in Ruby, which contains function, class variable (variable start with `@`) and user defined symbol. `Symbol.all_symbols` can be used to get all symbol name, w/o colon.</li>
<li>Symbol can not be used as a left value. It is just a symbol, can be used as right value.</li>
<li>For string comparison and hash index, a temp string will create a new object each time, which may reduce the performance.</li>
<li>There is a `to_s` method for symbol, and a `to_sym` method for string.</li>
<li>Save information in string if take more concern on content, and symbol for object id.</li>
<li>Hash (dict in python) can use any object as key, which is different with Python.</li>
<li>It is recommended to use symbol to replace the string index</li>
<li>Hash can be defined via `{key: val}` or `{key =&gt; val}`. If using the first method, the `key` can not be a string, but a name obey the variable rule, and Ruby will convert it to symbol. That is: {a: 2} == {:a =&gt; 2}</li>
</ul>
<h4>File</h4>
<ul>
<li>Usual way for using File: `File.open() do |f| .. end`</li>
<li>Can define file encoding and internal encoding in the open command, which is better than built-in `open` of Python</li>
<li>`Find.find()` will traverse the directory, include sub directory.</li>
<li>`File.new()` can open a random access file, which can response to `.seek` method.</li>
</ul>
<h4>Regular expression</h4>
<ul>
<li>Pattern enclosed by slash is an regular expression object, `/foobar/`</li>
<li>Both string and regular expression has match method. RE use `match` while string use `=~`.</li>
<li>`.match` in RE will return `MatchData` object of matched, or `nil` for not found.</li>
<li>`=~` in string will return index if found, or `nil` for not found.</li>
</ul>
<h4>Class</h4>
<ul>
<li>class is a first-class object in Ruby, which is an object of Class.</li>
<li>As mentioned before, the class name must has first character uppercased.</li>
<li>Create a new object with `ClassName.new`, which will invoke `allocate` method to allocate space and `initalize` method for initialization.</li>
<li>Variable with prefix `@` is class variable, which can be used in the whole object, seems like the `self.` variable in Python, but in Ruby, name with `self.` must function, then, the first character must be uppercased.</li>
<li>`methods` method can be used to printed out all methods in class, like the `dir` in Python.</li>
<li>`responsed_to?` method can be used to check whether the method exists in the object. If not, Ruby first will check whether there is `method_mission` method first, and then throw exception of not found.</li>
<li>Every class in Ruby is open, which means you can update any class, include built-in class like string, at anytime. But make sure you will not bring the conflict into exist class.</li>
<li>A more safer way is define a sub-class, and override the needed method.</li>
<li>In Ruby, one class can only be inherit from a single class. However, module can be used as multi inherit, seems like the interface in Java.</li>
<li>If calling `super` in one class, the method in parent class will be executed, but different syntax can cause different result:</li>
<li>Calling `super` with no parentheses, then the argument in sub method will be passed to parent method.</li>
<li>Calling `super` with empty parentheses, then the default value of parent method will be used, and error will be reported if no default value defined.</li>
<li>Calling `super` with value, then pass this value to parent method.</li>
<li>Abstract class, seems more like syntax sugar. Calling undefined method in parent class, and implement the method in subclass.</li>
<li>The default access rule for method in class is public, can add protect/private before def if needed.</li>
<li>Those access type can be only applied to method, the instance/class variable is private by default.</li>
</ul>
<h4>Proc</h4>
<ul>
<li>Like lambda in Python, but named Proc in Ruby.</li>
<li>Each code block created by `lambda` is a object of `Proc` class, which can be executed by calling `.call` method.</li>
<li>Here is a example for lambda with argument: `lambda {|x| &#8220;Hello #{x}&#8221;}`.call &#8220;Hell&#8221;`</li>
</ul>
<h4>Load and require</h4>
<ul>
<li>`load` and `require` are methods defined in `Object`, but more like a keyword during usage.</li>
<li>File included by `load` will be loaded every time program executed, while `require` only once.</li>
<li>Pass filename w/o suffix to `require`, and `require` will find the file in the path. If the suffix is rb, then imported as source file. For library suffix, like .so, .dll, `require` will import them as Ruby extension.</li>
<li>`require` will return `true` or `false` after execution complete.</li>
</ul>
<h4>Exception</h4>
<ul>
<li>A special class, user can throw it via `raise`.</li>
<li>Default exception type is `RuntimeError`, but can be changed by passing class name to `raise`</li>
<li>Use `rescue` to handle the exception.</li>
</ul>

<p><a href="http://feedads.g.doubleclick.net/~a/ma1FdOfU8D9j9xN5Aa6cj7liJsE/0/da"><img src="http://feedads.g.doubleclick.net/~a/ma1FdOfU8D9j9xN5Aa6cj7liJsE/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/ma1FdOfU8D9j9xN5Aa6cj7liJsE/1/da"><img src="http://feedads.g.doubleclick.net/~a/ma1FdOfU8D9j9xN5Aa6cj7liJsE/1/di" border="0" ismap="true"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.hzmangel.info/blog/archives/1101/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://www.hzmangel.info/blog/archives/1101</feedburner:origLink></item>
		<item>
		<title>2012，魔都开年</title>
		<link>http://feedproxy.google.com/~r/hzmangel/~3/S6h7cGqevUs/1078</link>
		<comments>http://www.hzmangel.info/blog/archives/1078#comments</comments>
		<pubDate>Wed, 11 Jan 2012 14:28:20 +0000</pubDate>
		<dc:creator>hzmangel</dc:creator>
				<category><![CDATA[那山那水]]></category>
		<category><![CDATA[旅行]]></category>

		<guid isPermaLink="false">http://www.hzmangel.info/blog/?p=1078</guid>
		<description><![CDATA[本来还在想今年开年行的地点，某人的婚礼邀请就发了过来，于是魔都就成了本年度开年行的目的地了~ 无锡 30号晚上就冲上了去无锡的动车，本来买的坐票，上车后惊喜的发现是软卧改的座，然后更惊喜的是旁边那俩是一对，最后的结果就是两张铺三个人好好的睡了一觉。除了没有床单被套枕巾，和普通的软卧没啥区别。早上打着哈欠推开包厢门，看到走道边坐着的昏昏欲睡的人们，心里暗道好运气~ 再一次站在无锡的火车站，与上次不同的是这次是在老站，也就是南广场下的车，不需要走那条坑爹的地道-过马路-地道线路（不过后来去上海的时候发现地道已经修通了，所以只需要抱怨地道长就好了，不用抱怨过马路了）。去无锡就是冲着小笼和馄饨的（当然明面上的主要任务是去慰问新进升级为娃他爹的某朋友），本想继续去出崇安寺上次吃的那一家王兴记，结果对着手机地图才发现想去的熙盛源是另有其地（上次去的时候还没有新手机，这次去的时候新手机已经被偷了，~~~&#62;.&#60;~~~）。作为一只吃货，我决定去那家没吃到的店。 顺着路走了好久，中间问了N个人路，但是悲催的是最多的一个听懂了一半，印象中上次来听他们说话没那么难懂的啊。路过赫赫有名的三凤桥老店（里面熟食部的人是里三层外三层，参考逢年过节的稻香村吧，而另一半卖真空包装的就没人，欺负外地人啊~），就给它家的招牌按了一张，嗯。话说，圈啊，你念念不忘的排骨就它家的哈~ 顺路继续再走个十来分钟就到了目的地，坐下要了个荠菜馄饨还有个小笼就开吃。当时也没想着拿相机出来拍，就随手用手机摁了一张，意思意思吧，嘿嘿~ 无锡的，差不多就这些了吧，这次纯路过，也没怎么玩，除了吃就是去朋友家坐着了，还玩了一下午的Wii。好吧，我承认我很无聊，娃他爹不知道…… &#160; 魔都 1号下午的动车去魔都，40分钟左右就已经站在虹桥火车站的地面上了，长三角的动车真方便……去酒店住下收拾好的时候天已经黑了，想了想还是决定去被本地人鄙视的南京路外滩放放风，谁让咱是硬盘人呢~ 嗯，我承认我十分的没创意，所以直接去的是第一食品，为小杨生煎啊。南京路上的人不比上次厦门中山路上的人少，还好没像上次那样碰到一堆售完的店。小杨生煎在第一食品二楼，里面还有好几家别的店，在入口处统一付钱。当时要了小杨生煎和它家的贡丸粉丝吧，一份别家的煎饺，还有一份第三家的老鸭粉丝汤。说实在的，味道一般，就算是生煎也没有什么太出彩的地方，好像还没有印象中小时候外婆家旁边早点摊上1块钱7个的生煎好吃，而且有意思的是，它家的生煎前的是有褶子的那一面，不知道是不是就是这样，反正就小奇怪就是啦。点的其它的东西完全没可以说道的地方，只上图不说话~ 在第一食品楼下还找到了别人推荐的凯司令，买了它家的粟子蛋糕，细细的粟子馅上铺一层奶油，很香，也很好吃。 吃完就晃去了江边，天冷的缘故吧，江边没有太多的，于是很从容的找到了个桥桩子摆上相机，拍下了本次唯为数不多除了吃的东西以外的照片（其实总共就俩……） 第二天中午和猫总俩口子吃的鹭鹭，本帮菜，发现有些地方和家里面的菜还是有些相似的，嗯。 第三天因为有事没走成，所以抓住最后一个晚上摸去了七叶和茶，号称是从隔壁某个岛上开过来的抹茶店。店里面的装修有种素雅的感觉，点的东西上来后有一股茶的清香，相比之前吃的抹茶，茶味和苦位更重一些吧。出门的时候没背相机，所以只好放几张打包的泡芙和提拉米苏照片上来了。 先放盒子，三个小小的盒子，看着很好看。拍照片的时候想玩焦外，可惜套头的焦外实在是……凑合看吧，LOL。 然后是提拉米苏，上面是一层很香的抹茶粉，然后下面的奶油中嵌着一块块的抹茶蛋糕。不过话说，我还是比较喜欢吃饼干做的那种，这个，有点腻…… 然后是泡芙。买了俩，一个抹茶，一个焙茶。颜色上一个绿一个黑，口感上也是一个轻一个重，不过，都好香的……话说，今天整理照片的时候才发现把抹茶的那一只拍的和隔壁岛国的天狗一样，当时咋没发现呢…… 最后，4号下午高铁回帝都，一路上没碰上雷雨停车追尾躲猫猫等事故，所以也就没啥写的了，丢张虹桥的照片吧~ PS：时间仓促，加上晚上太冷，所以，银行街啊，南京路啊，外滩啥的照片，等下次吧，上海帮还有好多人没见着呢。作为一个硬盘人，表示对上海帮众的不屑表示没看见，嗯。 PS2：在老城区里面乱转的时候，满喜欢那些两三层的房子的感觉的，不知道那边晚上会不会像天津那些风情区一样也有景观灯。 PSP：这次带了个小的八爪鱼架子去，没背大架子，结果发现，偷懒是不行滴，小架子是不靠谱滴…… PS3：上海的地铁感觉比北京方便，4号上午上班点出门也没感觉太挤，不过，票价啊，贵啊，更郁闷的是到了虹桥准备滚蛋的时候才发现原来可以有一日票卖，冤大头啊~ PSV：上海的路，咋都那么长呢，第一天下地铁去住的地方，上来先看到的门牌号就是22XX，那叫一个汗啊。本来以为是个例，咨询了上海帮众后发现是正常情况，唔，好吧，硬盘人啊硬盘人~]]></description>
			<content:encoded><![CDATA[<p>本来还在想今年开年行的地点，某人的婚礼邀请就发了过来，于是魔都就成了本年度开年行的目的地了~</p>
<p><span id="more-1078"></span><br />
<h4>无锡</h4>
<p>30号晚上就冲上了去无锡的动车，本来买的坐票，上车后惊喜的发现是软卧改的座，然后更惊喜的是旁边那俩是一对，最后的结果就是两张铺三个人好好的睡了一觉。除了没有床单被套枕巾，和普通的软卧没啥区别。早上打着哈欠推开包厢门，看到走道边坐着的昏昏欲睡的人们，心里暗道好运气~</p>
<p>再一次站在无锡的火车站，与上次不同的是这次是在老站，也就是南广场下的车，不需要走那条坑爹的地道-过马路-地道线路（不过后来去上海的时候发现地道已经修通了，所以只需要抱怨地道长就好了，不用抱怨过马路了）。去无锡就是冲着小笼和馄饨的（当然明面上的主要任务是去慰问新进升级为娃他爹的某朋友），本想继续去出崇安寺上次吃的那一家王兴记，结果对着手机地图才发现想去的熙盛源是另有其地（上次去的时候还没有新手机，这次去的时候新手机已经被偷了，~~~&gt;.&lt;~~~）。作为一只吃货，我决定去那家没吃到的店。</p>
<p>顺着路走了好久，中间问了N个人路，但是悲催的是最多的一个听懂了一半，印象中上次来听他们说话没那么难懂的啊。路过赫赫有名的三凤桥老店（里面熟食部的人是里三层外三层，参考逢年过节的稻香村吧，而另一半卖真空包装的就没人，欺负外地人啊~），就给它家的招牌按了一张，嗯。话说，圈啊，你念念不忘的排骨就它家的哈~</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:8747F07C-CDE8-481f-B0DF-C6CFD074BF67:9853662d-278e-49ad-8f1a-cc0e74f012b8" class="wlWriterEditableSmartContent"><a href="http://www.hzmangel.info/blog/wp-content/uploads/2012/01/1-8x6.jpg" title="招牌一枚" rel="thumbnail"><img border="0" src="http://www.hzmangel.info/blog/wp-content/uploads/2012/01/1.png" width="455" height="610" /></a></div>
<p>顺路继续再走个十来分钟就到了目的地，坐下要了个荠菜馄饨还有个小笼就开吃。当时也没想着拿相机出来拍，就随手用手机摁了一张，意思意思吧，嘿嘿~</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:8747F07C-CDE8-481f-B0DF-C6CFD074BF67:86200498-1b3a-49f1-b92c-16d51f77b2c0" class="wlWriterEditableSmartContent"><a href="http://www.hzmangel.info/blog/wp-content/uploads/2012/01/2-8x6.jpg" title="馄饨小笼和醋" rel="thumbnail"><img border="0" src="http://www.hzmangel.info/blog/wp-content/uploads/2012/01/2.png" width="580" height="448" /></a></div>
<p>无锡的，差不多就这些了吧，这次纯路过，也没怎么玩，除了吃就是去朋友家坐着了，还玩了一下午的Wii。好吧，我承认我很无聊，娃他爹不知道……</p>
<p>&#160;</p>
<h4>魔都</h4>
<p>1号下午的动车去魔都，40分钟左右就已经站在虹桥火车站的地面上了，长三角的动车真方便……去酒店住下收拾好的时候天已经黑了，想了想还是决定去被本地人鄙视的南京路外滩放放风，谁让咱是硬盘人呢~</p>
<p>嗯，我承认我十分的没创意，所以直接去的是第一食品，为小杨生煎啊。南京路上的人不比上次厦门中山路上的人少，还好没像上次那样碰到一堆售完的店。小杨生煎在第一食品二楼，里面还有好几家别的店，在入口处统一付钱。当时要了小杨生煎和它家的贡丸粉丝吧，一份别家的煎饺，还有一份第三家的老鸭粉丝汤。说实在的，味道一般，就算是生煎也没有什么太出彩的地方，好像还没有印象中小时候外婆家旁边早点摊上1块钱7个的生煎好吃，而且有意思的是，它家的生煎前的是有褶子的那一面，不知道是不是就是这样，反正就小奇怪就是啦。点的其它的东西完全没可以说道的地方，只上图不说话~</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:8747F07C-CDE8-481f-B0DF-C6CFD074BF67:dde56c40-4d9f-4321-b9b1-5054557e2edf" class="wlWriterEditableSmartContent"><a href="http://www.hzmangel.info/blog/wp-content/uploads/2012/01/3-8x6.jpg" title="看图不说话" rel="thumbnail"><img border="0" src="http://www.hzmangel.info/blog/wp-content/uploads/2012/01/3.png" width="580" height="485" /></a></div>
<p>在第一食品楼下还找到了别人推荐的凯司令，买了它家的粟子蛋糕，细细的粟子馅上铺一层奶油，很香，也很好吃。</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:8747F07C-CDE8-481f-B0DF-C6CFD074BF67:4d316a27-2967-4dcc-9a94-92382ee04308" class="wlWriterEditableSmartContent"><a href="http://www.hzmangel.info/blog/wp-content/uploads/2012/01/5-8x6.jpg" title="" rel="thumbnail"><img border="0" src="http://www.hzmangel.info/blog/wp-content/uploads/2012/01/5.png" width="580" height="455" /></a></div>
<p>吃完就晃去了江边，天冷的缘故吧，江边没有太多的，于是很从容的找到了个桥桩子摆上相机，拍下了本次唯为数不多除了吃的东西以外的照片（其实总共就俩……）</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:8747F07C-CDE8-481f-B0DF-C6CFD074BF67:2be372dd-0a24-4766-9dd5-732f416e9e23" class="wlWriterEditableSmartContent"><a href="http://www.hzmangel.info/blog/wp-content/uploads/2012/01/4-8x6.jpg" title="唔，东方明zhu~~" rel="thumbnail"><img border="0" src="http://www.hzmangel.info/blog/wp-content/uploads/2012/01/4.png" width="580" height="485" /></a></div>
<p>第二天中午和猫总俩口子吃的鹭鹭，本帮菜，发现有些地方和家里面的菜还是有些相似的，嗯。</p>
<p>第三天因为有事没走成，所以抓住最后一个晚上摸去了七叶和茶，号称是从隔壁某个岛上开过来的抹茶店。店里面的装修有种素雅的感觉，点的东西上来后有一股茶的清香，相比之前吃的抹茶，茶味和苦位更重一些吧。出门的时候没背相机，所以只好放几张打包的泡芙和提拉米苏照片上来了。</p>
<p>先放盒子，三个小小的盒子，看着很好看。拍照片的时候想玩焦外，可惜套头的焦外实在是……凑合看吧，LOL。</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:8747F07C-CDE8-481f-B0DF-C6CFD074BF67:42a4cdbd-b094-4ea7-89c3-b4bcffe71f94" class="wlWriterEditableSmartContent"><a href="http://www.hzmangel.info/blog/wp-content/uploads/2012/01/6-8x6.jpg" title="排排站~" rel="thumbnail"><img border="0" src="http://www.hzmangel.info/blog/wp-content/uploads/2012/01/6.png" width="580" height="485" /></a></div>
<p>然后是提拉米苏，上面是一层很香的抹茶粉，然后下面的奶油中嵌着一块块的抹茶蛋糕。不过话说，我还是比较喜欢吃饼干做的那种，这个，有点腻……</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:8747F07C-CDE8-481f-B0DF-C6CFD074BF67:c05c4fb0-7c9d-49cc-a393-c1f226800d0e" class="wlWriterEditableSmartContent"><a href="http://www.hzmangel.info/blog/wp-content/uploads/2012/01/7-8x6.jpg" title="" rel="thumbnail"><img border="0" src="http://www.hzmangel.info/blog/wp-content/uploads/2012/01/7.png" width="580" height="455" /></a></div>
<p>然后是泡芙。买了俩，一个抹茶，一个焙茶。颜色上一个绿一个黑，口感上也是一个轻一个重，不过，都好香的……话说，今天整理照片的时候才发现把抹茶的那一只拍的和隔壁岛国的天狗一样，当时咋没发现呢……</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:8747F07C-CDE8-481f-B0DF-C6CFD074BF67:c5796dd3-d5be-4353-b562-4a8c89356c19" class="wlWriterEditableSmartContent"><a href="http://www.hzmangel.info/blog/wp-content/uploads/2012/01/DSC_6758-8x6.jpg" title="天狗吃泡芙 -_-!!!" rel="thumbnail"><img border="0" src="http://www.hzmangel.info/blog/wp-content/uploads/2012/01/DSC_6758.png" width="580" height="310" /></a></div>
<p>最后，4号下午高铁回帝都，一路上没碰上雷雨停车追尾躲猫猫等事故，所以也就没啥写的了，丢张虹桥的照片吧~</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:8747F07C-CDE8-481f-B0DF-C6CFD074BF67:c8658453-01cb-474a-b917-537e3872e53c" class="wlWriterEditableSmartContent"><a href="http://www.hzmangel.info/blog/wp-content/uploads/2012/01/8-8x6.jpg" title="" rel="thumbnail"><img border="0" src="http://www.hzmangel.info/blog/wp-content/uploads/2012/01/8.png" width="580" height="411" /></a></div>
<p>PS：时间仓促，加上晚上太冷，所以，银行街啊，南京路啊，外滩啥的照片，等下次吧，上海帮还有好多人没见着呢。作为一个硬盘人，表示对上海帮众的不屑表示没看见，嗯。   <br />PS2：在老城区里面乱转的时候，满喜欢那些两三层的房子的感觉的，不知道那边晚上会不会像天津那些风情区一样也有景观灯。    <br />PSP：这次带了个小的八爪鱼架子去，没背大架子，结果发现，偷懒是不行滴，小架子是不靠谱滴……    <br />PS3：上海的地铁感觉比北京方便，4号上午上班点出门也没感觉太挤，不过，票价啊，贵啊，更郁闷的是到了虹桥准备滚蛋的时候才发现原来可以有一日票卖，冤大头啊~    <br />PSV：上海的路，咋都那么长呢，第一天下地铁去住的地方，上来先看到的门牌号就是22XX，那叫一个汗啊。本来以为是个例，咨询了上海帮众后发现是正常情况，唔，好吧，硬盘人啊硬盘人~</p>

<p><a href="http://feedads.g.doubleclick.net/~a/uJVXKWPWc3iitZmPzpTfIM2AxXg/0/da"><img src="http://feedads.g.doubleclick.net/~a/uJVXKWPWc3iitZmPzpTfIM2AxXg/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/uJVXKWPWc3iitZmPzpTfIM2AxXg/1/da"><img src="http://feedads.g.doubleclick.net/~a/uJVXKWPWc3iitZmPzpTfIM2AxXg/1/di" border="0" ismap="true"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.hzmangel.info/blog/archives/1078/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://www.hzmangel.info/blog/archives/1078</feedburner:origLink></item>
		<item>
		<title>List all CVS tags</title>
		<link>http://feedproxy.google.com/~r/hzmangel/~3/_c7btLpCqks/1052</link>
		<comments>http://www.hzmangel.info/blog/archives/1052#comments</comments>
		<pubDate>Mon, 19 Dec 2011 02:41:55 +0000</pubDate>
		<dc:creator>hzmangel</dc:creator>
				<category><![CDATA[Happy coding]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.hzmangel.info/blog/?p=1052</guid>
		<description><![CDATA[最近在折腾一个CVS的库，需要把它里面所有的tags给列出来，在网上找了一个Perl脚本，以前一直是直接用的，那天看了看发现原来不是很难，于是写了一个Python的，为的是可以当成函数嵌到我的脚本中。 脚本的原理就是检查一个working directory中所有文件的status，然后把输出的内容去重。脚本运行需要设置好CVSROOT环境变量，而且需要提供一个CVS的工作目录作为参数。 #!/usr/bin/python import re import os import sys import subprocess as sp def get_all_tags(cvs_wdir): is_tag_line = False cvs_cmd = 'cvs -Q status -R -v' cvs_tag_pattern = re.compile(r'(\w+)\s+') tmp_tags = [] os.chdir(cvs_wdir) cmd_pipe = sp.Popen(cvs_cmd, shell=True, stdout=sp.PIPE) for line &#8230; <a href="http://www.hzmangel.info/blog/archives/1052">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>最近在折腾一个CVS的库，需要把它里面所有的tags给列出来，在网上找了一个<a href="http://docs.codehaus.org/display/ninja/List+CVS+Tags" target="_blank">Perl脚本</a>，以前一直是直接用的，那天看了看发现原来不是很难，于是写了一个Python的，为的是可以当成函数嵌到我的脚本中。</p>
<p><span id="more-1052"></span></p>
<p>脚本的原理就是检查一个working directory中所有文件的status，然后把输出的内容去重。脚本运行需要设置好CVSROOT环境变量，而且需要提供一个CVS的工作目录作为参数。</p>
<pre class="brush: python">#!/usr/bin/python

import re
import os
import sys
import subprocess as sp

def get_all_tags(cvs_wdir):
    is_tag_line = False
    cvs_cmd = 'cvs -Q status -R -v'
    cvs_tag_pattern = re.compile(r'(\w+)\s+')
    tmp_tags = []

    os.chdir(cvs_wdir)
    cmd_pipe = sp.Popen(cvs_cmd, shell=True, stdout=sp.PIPE)

    for line in cmd_pipe.stdout.readlines():
        if 'Existing Tags' in line:
            is_tag_line = True
            continue

        if not is_tag_line:
            continue

        if '============' in line and is_tag_line == True:
            is_tag_line = 0
            continue

        line = line.strip()
        if line != '':
            try:
                tag = cvs_tag_pattern.findall(line.strip())[0]
            except IndexError:
                print line
                raise
            tmp_tags.append(tag)

    return set(tmp_tags)

if __name__ == '__main__':
    print '\n'.join(sorted(get_all_tags(sys.argv[1])))</pre>
<p>话说，有人能提供更好的办法吗？然后，有人可以告诉我，这个东西取出来的东西是全部的tag吗？没用过CVS&#8230;&#8230;</p>

<p><a href="http://feedads.g.doubleclick.net/~a/JPSgo8hxoJ5sv3qiQH6ZPT3CHHo/0/da"><img src="http://feedads.g.doubleclick.net/~a/JPSgo8hxoJ5sv3qiQH6ZPT3CHHo/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/JPSgo8hxoJ5sv3qiQH6ZPT3CHHo/1/da"><img src="http://feedads.g.doubleclick.net/~a/JPSgo8hxoJ5sv3qiQH6ZPT3CHHo/1/di" border="0" ismap="true"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.hzmangel.info/blog/archives/1052/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://www.hzmangel.info/blog/archives/1052</feedburner:origLink></item>
		<item>
		<title>Simple Life Game in HTML5</title>
		<link>http://feedproxy.google.com/~r/hzmangel/~3/FcrECvn6nbw/1049</link>
		<comments>http://www.hzmangel.info/blog/archives/1049#comments</comments>
		<pubDate>Mon, 28 Nov 2011 18:13:59 +0000</pubDate>
		<dc:creator>hzmangel</dc:creator>
				<category><![CDATA[Happy coding]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.hzmangel.info/blog/?p=1049</guid>
		<description><![CDATA[想着好久没写blog了，刚好在看计算中的上帝时，里面有提到生命游戏，所以就顺手写了一个，顺便凑篇文章。 先说说HTML5。看过一堆HTML5的应用，也想着自己做一些东西出来，挑来捡去最后还是选中的Canvas，可能还是对音视频不是十分感冒吧。Canvas是HTML5中新加的一个元素，主要作用就是在网页上直接画画。Canvas是一个矩形的区域，可以通过JavaScript程序控制上面的每一个像素。个人感觉和普通的GUI程序十分类似。 下面是Life Game，wiki链接在此。这是一个零玩家游戏，其实它就是一个简单的状态机。在一个点阵中，每个点都有0, 1两种状态，分别表示这个点的死与生。某个点的下一步的状态由它周围的8个点决定。周围的点数过多或者过少都会造成此点的死亡（生命是多么的不容易啊~）。规则很简单，只有4条，但是由这4条规则可以演化出许多好玩的东西，据说如果时间够长的话，可以看到从混沌到有序这一神奇的过程，唔，我是还没看到大规模有序的出现，以后再说吧~ 至于算法&#8230;..就是拿JS写了个最简单的，把所有状态存放在一个二维数组中，每一步去遍历这个数组，然后根据周边点的状态决定被遍历点下一步该是生还是灭。很暴力的直接循环了，三年前的小破本T61还是能跑的起来的，嗯~ 目前程序的初始状态是随机生成5e4个点放在Canvas中，以后如果有空的话，会考虑从本地文件中载入点的座标以及存储点到本地文件中，可以以后接着算，据说HTML5有对本地存储据做支持，就当继续学吧。 网页的地址在 http://www.hzmangel.info/html5/life/life.html ，start开始跑，stop停止，每刷新一次会重新生成一堆随机点。size表示点的边长，最小值是2吧，其实算是在程序里面hard code的了，下面那个speed是每一步的时间，如果有更改记得改完后点update。程序是用HTML5(Canvas+FormWidget)+CSS3(圆角框)+WebFonts(G家的服务)弄的，所以请自行选择靠谱的浏览器和网络环境~]]></description>
			<content:encoded><![CDATA[<p>想着好久没写blog了，刚好在看<a title="计算中的上帝-豆瓣" href="http://book.douban.com/subject/1140726/" target="_blank">计算中的上帝</a>时，里面有提到生命游戏，所以就顺手写了一个，顺便凑篇文章。<br />
<span id="more-1049"></span>先说说HTML5。看过一堆HTML5的应用，也想着自己做一些东西出来，挑来捡去最后还是选中的Canvas，可能还是对音视频不是十分感冒吧。Canvas是HTML5中新加的一个元素，主要作用就是在网页上直接画画。Canvas是一个矩形的区域，可以通过JavaScript程序控制上面的每一个像素。个人感觉和普通的GUI程序十分类似。</p>
<p>下面是Life Game，wiki链接<a title="GameOfLife" href="http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life" target="_blank">在此</a>。这是一个零玩家游戏，其实它就是一个简单的状态机。在一个点阵中，每个点都有0, 1两种状态，分别表示这个点的死与生。某个点的下一步的状态由它周围的8个点决定。周围的点数过多或者过少都会造成此点的死亡（生命是多么的不容易啊~）。规则很简单，只有4条，但是由这4条规则可以演化出许多好玩的东西，据说如果时间够长的话，可以看到从混沌到有序这一神奇的过程，唔，我是还没看到大规模有序的出现，以后再说吧~</p>
<p>至于算法&#8230;..就是拿JS写了个最简单的，把所有状态存放在一个二维数组中，每一步去遍历这个数组，然后根据周边点的状态决定被遍历点下一步该是生还是灭。很暴力的直接循环了，三年前的小破本T61还是能跑的起来的，嗯~</p>
<p>目前程序的初始状态是随机生成5e4个点放在Canvas中，以后如果有空的话，会考虑从本地文件中载入点的座标以及存储点到本地文件中，可以以后接着算，据说HTML5有对本地存储据做支持，就当继续学吧。</p>
<p>网页的地址在 <a href="http://www.hzmangel.info/html5/life/life.html">http://www.hzmangel.info/html5/life/life.html</a> ，start开始跑，stop停止，每刷新一次会重新生成一堆随机点。size表示点的边长，最小值是2吧，其实算是在程序里面hard code的了，下面那个speed是每一步的时间，如果有更改记得改完后点update。程序是用HTML5(Canvas+FormWidget)+CSS3(圆角框)+WebFonts(G家的服务)弄的，所以请自行选择靠谱的浏览器和网络环境~</p>

<p><a href="http://feedads.g.doubleclick.net/~a/XlMQsrVRaQI-HpJrPKZx7SECj8E/0/da"><img src="http://feedads.g.doubleclick.net/~a/XlMQsrVRaQI-HpJrPKZx7SECj8E/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/XlMQsrVRaQI-HpJrPKZx7SECj8E/1/da"><img src="http://feedads.g.doubleclick.net/~a/XlMQsrVRaQI-HpJrPKZx7SECj8E/1/di" border="0" ismap="true"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.hzmangel.info/blog/archives/1049/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.hzmangel.info/blog/archives/1049</feedburner:origLink></item>
		<item>
		<title>Blocking/Non-Blocking IO and SYN/ASYN IO</title>
		<link>http://feedproxy.google.com/~r/hzmangel/~3/W4xpF2PhOQ0/1035</link>
		<comments>http://www.hzmangel.info/blog/archives/1035#comments</comments>
		<pubDate>Sun, 04 Sep 2011 14:18:55 +0000</pubDate>
		<dc:creator>hzmangel</dc:creator>
				<category><![CDATA[Happy coding]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.hzmangel.info/blog/?p=1035</guid>
		<description><![CDATA[这是我上个月linuxfb版聚上讲的话题，因为后续还有一些讨论的东西，所以就一并在这记一下。估计下个月听完Bergwolf的AIO还会有些更新。 首先是上次版聚的片子，做的一般，凑合看吧，呵呵。有些片子里面列出来的东西就不细说了，主要说的可能还是版聚完后查的AIO相关的一些东西。 20110828 Non blocking socket View more presentations from linuxfb 讲到异步IO这块的时候讨论比较激烈，主要就是在异步IO和非阻塞IO之间的区别。课后做了些功课，于是有了下面这些玩意，如有走过路过发现不对的，敬请指正，在此先行谢过，呵呵。 =================================================== ASYNC/SYNC 和 Blocking/Non-Blocking其实可以说是不相干的两个东西，但是由于使用的时候会有特定的组合，所以有时也就混为一谈了。分别在Internet和大中华局域网转了转，找到两篇文章[1][3]，比着上次的幻灯小总结一下吧。 先从 Dai Jun 后来临时找的幻灯说起，那个片子把IO的时间分成了两个阶段，第一阶段是从应用程序发起请求开始到数据准备完毕结束，第二阶段是把数据从内核态拷贝到用户态。对于应用程序而言，当第二阶段结束后，就表示数据可以使用了，也就是这次IO操作完成。 首先说Blocking/Non-Blocking，阻塞和非阻塞的区别其实很简单，就是应用程序在等待数据的过程中，是否可以做其它的事情。例如最简单的SYN Blocking操作，程序调了个read()就后就把自己拍晕然后等着被返回的数据砸醒，晕了程序当然不能干活，所以它就是阻塞的。在文章[1]中，有几个很形象的示意图，可以很方便的看出区别。 再说说ASYN/SYN。同步和异步，主要描述的是消息通知的机制([3])，同步是指内核在处理完请求后，不会告诉程序数据已经准备好了，而需要程序自己去检查；而异步的情况下，请求处理完成后内核会发给程序一个通知。所以，对于悲催的Non-Blocking SYN的模式，程序需要一遍又一遍的去检查数据是不是好了，效率可能还没有Blocking SYN的高。而IO复用，即select()/epoll()的方案，虽然也有阻塞，但是终归它是由系统告知某个fd可用的，所以是异步的IO。至于AIO，把等待数据这个过程也省去了，直接发完请求该干嘛干嘛，等着被叫号就好了。 所以那天片子里面说的AIO，应该就是指Non-Blocking ASYN的情况，此文中下面写的AIO，都是指这种情况，即非阻塞异步IO。 说完了区别，再来给AIO补一点东西。 在Linux中，AIO有两种接口，一种是glibc提供的POSIX异步IO接口，即aio_*函数系；另一种是Linux的原生异步IO接口，是由libaio提供的。POSIX AIO是在用户空间通过线程+阻塞模拟并发操作来实现的，所以性能上没有太多出彩的地方，但是libaio是原生的AIO实现，性能上会好很多[2][4]。这个库好像最早是Oracle弄出来的，在Oracle/DB2中有应用。它使用不同于read()/write()的一套接口，具体的程序我也没看，不过应该是可以用在网络环境中的。 至于为什么现在还是用epoll撑起大半边天，可能是因为还没有到需要大规模考虑C1000K问题的时候吧，还有就是AIO的编程模型和传统模型的差别不是一点半点，基本上整个架构都需要推倒重来，相比于这个带来的风险，还是直接加服务器比较保险。不过TB已经有童鞋在折腾这些东西了，在slideshare上找到一个片子，有兴趣的可以去围观一下： http://www.slideshare.net/mryufeng/c1000k 。话说，这个是不是丢给 Bergwolf 就好？ 差不多就这些了，不知道有没有理解错的地方。最后是参考文献 [1] Boost application performance &#8230; <a href="http://www.hzmangel.info/blog/archives/1035">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>这是我上个月<a title="linuxfb" href="http://linuxfb.net" target="_blank">linuxfb</a>版聚上讲的话题，因为后续还有一些讨论的东西，所以就一并在这记一下。估计下个月听完Bergwolf的AIO还会有些更新。<span id="more-1035"></span></p>
<p>首先是上次版聚的片子，做的一般，凑合看吧，呵呵。有些片子里面列出来的东西就不细说了，主要说的可能还是版聚完后查的AIO相关的一些东西。</p>
<div id="__ss_9043269" style="width: 425px;"><strong style="display: block; margin: 12px 0 4px;"><a title="20110828 Non blocking socket" href="http://www.slideshare.net/linuxfb/non-blocking-socket" target="_blank">20110828 Non blocking socket</a></strong> <iframe src="http://www.slideshare.net/slideshow/embed_code/9043269" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" width="425" height="355"></iframe></p>
<div style="padding: 5px 0 12px;">View more <a href="http://www.slideshare.net/" target="_blank">presentations</a> from <a href="http://www.slideshare.net/linuxfb" target="_blank">linuxfb</a></div>
</div>
<p>讲到异步IO这块的时候讨论比较激烈，主要就是在异步IO和非阻塞IO之间的区别。课后做了些功课，于是有了下面这些玩意，如有走过路过发现不对的，敬请指正，在此先行谢过，呵呵。</p>
<p>===================================================</p>
<p>ASYNC/SYNC 和 Blocking/Non-Blocking其实可以说是不相干的两个东西，但是由于使用的时候会有特定的组合，所以有时也就混为一谈了。分别在Internet和大中华局域网转了转，找到两篇文章[1][3]，比着上次的幻灯小总结一下吧。</p>
<p>先从 Dai Jun 后来临时找的幻灯说起，那个片子把IO的时间分成了两个阶段，第一阶段是从应用程序发起请求开始到数据准备完毕结束，第二阶段是把数据从内核态拷贝到用户态。对于应用程序而言，当第二阶段结束后，就表示数据可以使用了，也就是这次IO操作完成。</p>
<p>首先说Blocking/Non-Blocking，阻塞和非阻塞的区别其实很简单，就是应用程序在等待数据的过程中，是否可以做其它的事情。例如最简单的SYN Blocking操作，程序调了个read()就后就把自己拍晕然后等着被返回的数据砸醒，晕了程序当然不能干活，所以它就是阻塞的。在文章[1]中，有几个很形象的示意图，可以很方便的看出区别。</p>
<p>再说说ASYN/SYN。同步和异步，主要描述的是消息通知的机制([3])，同步是指内核在处理完请求后，不会告诉程序数据已经准备好了，而需要程序自己去检查；而异步的情况下，请求处理完成后内核会发给程序一个通知。所以，对于悲催的Non-Blocking SYN的模式，程序需要一遍又一遍的去检查数据是不是好了，效率可能还没有Blocking SYN的高。而IO复用，即select()/epoll()的方案，虽然也有阻塞，但是终归它是由系统告知某个fd可用的，所以是异步的IO。至于AIO，把等待数据这个过程也省去了，直接发完请求该干嘛干嘛，等着被叫号就好了。</p>
<p>所以那天片子里面说的AIO，应该就是指Non-Blocking ASYN的情况，此文中下面写的AIO，都是指这种情况，即非阻塞异步IO。</p>
<p>说完了区别，再来给AIO补一点东西。</p>
<p>在Linux中，AIO有两种接口，一种是glibc提供的POSIX异步IO接口，即aio_*函数系；另一种是Linux的原生异步IO接口，是由libaio提供的。POSIX AIO是在用户空间通过线程+阻塞模拟并发操作来实现的，所以性能上没有太多出彩的地方，但是libaio是原生的AIO实现，性能上会好很多[2][4]。这个库好像最早是Oracle弄出来的，在Oracle/DB2中有应用。它使用不同于read()/write()的一套接口，具体的程序我也没看，不过应该是可以用在网络环境中的。</p>
<p>至于为什么现在还是用epoll撑起大半边天，可能是因为还没有到需要大规模考虑C1000K问题的时候吧，还有就是AIO的编程模型和传统模型的差别不是一点半点，基本上整个架构都需要推倒重来，相比于这个带来的风险，还是直接加服务器比较保险。不过TB已经有童鞋在折腾这些东西了，在slideshare上找到一个片子，有兴趣的可以去围观一下：</p>
<p><a href="http://www.slideshare.net/mryufeng/c1000k" target="_blank">http://www.slideshare.net/<wbr>mryufeng/c1000k</wbr></a> 。话说，这个是不是丢给 Bergwolf 就好？</p>
<p>差不多就这些了，不知道有没有理解错的地方。最后是参考文献</p>
<p>[1] Boost application performance using asynchronous I/O, M. Tim Jones, <a href="http://www.ibm.com/developerworks/linux/library/l-async/" target="_blank">http://www.ibm.com/developerworks/linux/library/l-async/</a></p>
<p>[2] Linux Asynchronous I/O Design: Evolution &amp; Challenge, Suparna Bhattacharya, <a href="http://www.kernel.org/pub/linux/kernel/people/suparna/aio-linux.pdf" target="_blank">http://www.kernel.org/pub/linux/kernel/people/suparna/aio-linux.pdf</a></p>
<p>[3] 同步/异步与阻塞/非阻塞的区别, <a href="http://www.cppblog.com/converse/archive/2009/05/13/82879.html" target="_blank">http://www.cppblog.com/converse/archive/2009/05/13/82879.html</a></p>
<p>[4] High Performance Solid State Storage Under Linux, Eric Seppanen, Matthew T. O’Keefe, David J. Lilja, <a href="http://storageconference.org/2010/Papers/MSST/Seppanen.pdf" target="_blank">http://storageconference.org/2010/Papers/MSST/Seppanen.pdf</a></p>

<p><a href="http://feedads.g.doubleclick.net/~a/WYo6c1p2sEUZIQlg8jZX9_WNjgg/0/da"><img src="http://feedads.g.doubleclick.net/~a/WYo6c1p2sEUZIQlg8jZX9_WNjgg/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/WYo6c1p2sEUZIQlg8jZX9_WNjgg/1/da"><img src="http://feedads.g.doubleclick.net/~a/WYo6c1p2sEUZIQlg8jZX9_WNjgg/1/di" border="0" ismap="true"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.hzmangel.info/blog/archives/1035/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.hzmangel.info/blog/archives/1035</feedburner:origLink></item>
		<item>
		<title>木兰围场塞罕坝</title>
		<link>http://feedproxy.google.com/~r/hzmangel/~3/09kU8Ywh7nY/1031</link>
		<comments>http://www.hzmangel.info/blog/archives/1031#comments</comments>
		<pubDate>Mon, 18 Jul 2011 15:48:20 +0000</pubDate>
		<dc:creator>hzmangel</dc:creator>
				<category><![CDATA[那山那水]]></category>
		<category><![CDATA[摄影]]></category>
		<category><![CDATA[旅行]]></category>

		<guid isPermaLink="false">http://www.hzmangel.info/blog/archives/1031</guid>
		<description><![CDATA[嗯，公司组织的TeamBuilding，找了个所谓的旅行社跟着走的？不多说啥了，先放照片，最后吐槽。 金莲 这次出门转一圈最大的收获可能就是看到金莲了吧。这几年一直怨念没有时间去小五看金莲，这次算是看了个够。尤其是第三天在乌兰布统，绵延到远处山脚下的草原上，灿烂的金莲像满天星斗一样点缀期其中。可能没有小五那么好看，但是也已经心满意足鸟~ 晚霞 第一天下了两场雨，所以天上的云格外的多。晚饭后照例拿起相机出门乱逛，不经意间就发现了天边的一抹红云，于是不顾旁边狂吠不止的大黄狗，开始一阵狂拍。前后也就十分钟的时间，当我喂饱了相机卡开始慢悠悠的往回走的时候，才看到匆匆赶来的同事们，唔，好像他们就没拍到啥了~ 日出 虽然之前去内蒙和泰山已经看过了日出，但是还是没有禁的住他们的撺掇，决定了再去看一次日出。虽然周六喝了点酒，依然在周日清晨3点半把自己给从床上拽了起来。和他们坐上包的小面，开到某个土坡脚下开始爬山。绕过一丛又一丛树，终于在东方微亮的时候找到了个视野开阔的地方。支上架子摆好相机，在等待日出的同时和头上大群的蚊子做着不屈不挠的斗争…… 遗珠 还有些片子不好归类，就都丢这吧~ &#160; 吐槽 照片发放完毕，下面进入本文最后一个环节：吐槽~~~ 食：这次是我吃过的最难吃的农家饭，没有之一。先不说味道，以前吃的饭好歹能有一个硬点的菜，这次到好，除了那个烤全羊（这个后面专门吐槽），就没见到过能当作肉块的东西。那家的豆腐和南瓜味道倒是不错，不过我估计是个农家乐都能做出来这玩意，而且还比TA家的好吃。 住：住过的最没有性价比的农家，同样没有之一。据说100一间一晚的标间，窗户直接通到院子还锁不上，屋里没有空调（第二天听到隔壁有一家几口晚上睡觉被冻的嗞哇乱叫在那和老板掐），热水器基本没出来过热水，水龙头的水是用来滴水穿石的。嗯，住的地方叫金塞山庄，好像还是跟车导游家老姨开的，可以直接拉黑了（后面还要拉黑一个），嗯。 黑：那边真TMD的黑啊： 草地摩托100一小时，想去年去丰宁的时候也就40。CPI再涨也不带这么玩的。 第一天晚上在外面找了家店吃烤全羊，店里面（还不是超市）18一瓶的酒能卖到70。 住的地方给的烤全羊居然TMD是挂炉烤的，一点烟火味都没有，真不如白煮，羊杂做汤还要单独收钱。上烤全羊那天晚上先上一堆米饭馒头 晚上说有篝火，随便拿了十来根树枝往竖的铁棍子上一靠，浇点汽油，那火是大，不到20分钟就点的连火都烤不成了。 第三天早上包的小面看日出，给带到的地方烂不说，还开口要350，那点路在北京顶多60出头。 景点骑马50一小时还是人牵着遛的，关键是那人还是走着牵着马，这哪是骑马啊，是明明是遛人有木有。 跟车的那个导游啥事不干就会跟着车跑，然后到地方说一声到哪了留多少时间就不见影子了，最多会介绍一下这边哪家店是他哪个亲戚开的，然后后面此地无银的加上一句不鼓励大家乱购物哈…. 景：最想吐槽的就是这个，去之前听人说的天花乱坠地涌金莲说那有多么好看，号称风景最美的坝上，结果到了那边大失所望。这TM哪是草原啊，之前去丰宁那次我还以为我没看到那边所谓的京北第一草原，结果到了这号称风景最好的坝上才发现，坝上和草原放一起说的时候，人们省略了两个定语和一个连词，其实它的全称是河北的坝上和内蒙的草原……最不能忍的是那边晚上居然看不见星星，本来带着架子是想去拍银河的，结果连找个北斗都要维持45度仰望天空的姿势10秒以上才能看见，帝都大风天的晚上看到的星星也比这多啊。还有那些神马还珠格格康熙王朝外景地，到了那边直接吐槽无力了。 差不多就这些了吧，该说的都说了，反正归到最后一句话就是如果没去过草原千万不要把第一次给坝上啊。以后想骑马骑摩托的直接去丰宁，离北京也近。想看景色的再多跑点至少去锡盟吧，300多公里都开出来了也不再多这100来公里，况且到赤峰还有火车，当然呼伦贝尔或青海或西藏会更好。对于我来说，估计以后会把坝上直接拉黑了吧（第二个被拉黑的登场），因为相比于骑马，我还是更愿意看风景吧，而坝上的风景，唔，吐槽无力了~~]]></description>
			<content:encoded><![CDATA[<p>嗯，公司组织的TeamBuilding，找了个所谓的旅行社跟着走的？不多说啥了，先放照片，最后吐槽。</p>
<p><span id="more-1031"></span><br />
<h2>金莲</h2>
<p>这次出门转一圈最大的收获可能就是看到金莲了吧。这几年一直怨念没有时间去小五看金莲，这次算是看了个够。尤其是第三天在乌兰布统，绵延到远处山脚下的草原上，灿烂的金莲像满天星斗一样点缀期其中。可能没有小五那么好看，但是也已经心满意足鸟~</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:8747F07C-CDE8-481f-B0DF-C6CFD074BF67:ea713147-845b-4867-8580-26c32493bf4b" class="wlWriterEditableSmartContent"><a href="http://www.hzmangel.info/blog/wp-content/uploads/2011/07/DSC_5599-8x6.jpg" title="雨后初霁，洒在花瓣上的阳光" rel="thumbnail"><img border="0" src="http://www.hzmangel.info/blog/wp-content/uploads/2011/07/DSC_5599.png" width="621" height="534" /></a></div>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:8747F07C-CDE8-481f-B0DF-C6CFD074BF67:e3728392-46c2-4a44-9949-3d186a7dc999" class="wlWriterEditableSmartContent"><a href="http://www.hzmangel.info/blog/wp-content/uploads/2011/07/DSC_5601-8x6.jpg" title="" rel="thumbnail"><img border="0" src="http://www.hzmangel.info/blog/wp-content/uploads/2011/07/DSC_5601.png" width="618" height="504" /></a></div>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:8747F07C-CDE8-481f-B0DF-C6CFD074BF67:e56024f7-cab0-4a60-b548-5592fa9d5b4a" class="wlWriterEditableSmartContent"><a href="http://www.hzmangel.info/blog/wp-content/uploads/2011/07/DSC_5609-8x6.jpg" title="通透的花瓣" rel="thumbnail"><img border="0" src="http://www.hzmangel.info/blog/wp-content/uploads/2011/07/DSC_5609.png" width="507" height="648" /></a></div>
<p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:8747F07C-CDE8-481f-B0DF-C6CFD074BF67:1bb7aee0-b1f4-40bb-b542-690d97fc0c75" class="wlWriterEditableSmartContent"><a href="http://www.hzmangel.info/blog/wp-content/uploads/2011/07/DSC_5671-8x6.jpg" title="" rel="thumbnail"><img border="0" src="http://www.hzmangel.info/blog/wp-content/uploads/2011/07/DSC_5671.png" width="580" height="455" /></a></div>
</p>
<h2>晚霞</h2>
<p>第一天下了两场雨，所以天上的云格外的多。晚饭后照例拿起相机出门乱逛，不经意间就发现了天边的一抹红云，于是不顾旁边狂吠不止的大黄狗，开始一阵狂拍。前后也就十分钟的时间，当我喂饱了相机卡开始慢悠悠的往回走的时候，才看到匆匆赶来的同事们，唔，好像他们就没拍到啥了~</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:8747F07C-CDE8-481f-B0DF-C6CFD074BF67:365923ef-820c-45b5-b663-6e7001c0583e" class="wlWriterEditableSmartContent"><a href="http://www.hzmangel.info/blog/wp-content/uploads/2011/07/DSC_5625-8x6.jpg" title="红云漫天" rel="thumbnail"><img border="0" src="http://www.hzmangel.info/blog/wp-content/uploads/2011/07/DSC_5625.png" width="580" height="485" /></a></div>
<h2>日出</h2>
<p>虽然之前去内蒙和泰山已经看过了日出，但是还是没有禁的住他们的撺掇，决定了再去看一次日出。虽然周六喝了点酒，依然在周日清晨3点半把自己给从床上拽了起来。和他们坐上包的小面，开到某个土坡脚下开始爬山。绕过一丛又一丛树，终于在东方微亮的时候找到了个视野开阔的地方。支上架子摆好相机，在等待日出的同时和头上大群的蚊子做着不屈不挠的斗争……</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:8747F07C-CDE8-481f-B0DF-C6CFD074BF67:8b6caa8e-525c-407a-a61f-d3bc6a9ad026" class="wlWriterEditableSmartContent"><a href="http://www.hzmangel.info/blog/wp-content/uploads/2011/07/DSC_5797-8x6.jpg" title="清晨4:16，日出前的天空" rel="thumbnail"><img border="0" src="http://www.hzmangel.info/blog/wp-content/uploads/2011/07/DSC_5797.png" width="580" height="485" /></a></div>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:8747F07C-CDE8-481f-B0DF-C6CFD074BF67:349b9446-539e-483d-92a1-78f9f795d894" class="wlWriterEditableSmartContent"><a href="http://www.hzmangel.info/blog/wp-content/uploads/2011/07/DSC_5812-8x6.jpg" title="树丛中飘逸的晨雾" rel="thumbnail"><img border="0" src="http://www.hzmangel.info/blog/wp-content/uploads/2011/07/DSC_5812.png" width="580" height="485" /></a></div>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:8747F07C-CDE8-481f-B0DF-C6CFD074BF67:f1648100-ce6e-40c2-8b74-b4b80f63f865" class="wlWriterEditableSmartContent"><a href="http://www.hzmangel.info/blog/wp-content/uploads/2011/07/DSC_5815-8x6.jpg" title="日出前夕的日柱" rel="thumbnail"><img border="0" src="http://www.hzmangel.info/blog/wp-content/uploads/2011/07/DSC_5815.png" width="580" height="485" /></a></div>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:8747F07C-CDE8-481f-B0DF-C6CFD074BF67:855e84dc-6ac3-4c73-ab74-a52ea2d8f9ca" class="wlWriterEditableSmartContent"><a href="http://www.hzmangel.info/blog/wp-content/uploads/2011/07/DSC_5816-8x6.jpg" title="日柱特写" rel="thumbnail"><img border="0" src="http://www.hzmangel.info/blog/wp-content/uploads/2011/07/DSC_5816.png" width="455" height="610" /></a></div>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:8747F07C-CDE8-481f-B0DF-C6CFD074BF67:89d336f2-a630-4d15-ae55-c62f8be090eb" class="wlWriterEditableSmartContent"><a href="http://www.hzmangel.info/blog/wp-content/uploads/2011/07/DSC_5839-8x6.jpg" title="半个太阳爬上来" rel="thumbnail"><img border="0" src="http://www.hzmangel.info/blog/wp-content/uploads/2011/07/DSC_5839.png" width="580" height="485" /></a></div>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:8747F07C-CDE8-481f-B0DF-C6CFD074BF67:b5c42f09-439a-405a-9237-6391b05d873a" class="wlWriterEditableSmartContent"><a href="http://www.hzmangel.info/blog/wp-content/uploads/2011/07/DSC_5853-8x6.jpg" title="守望日出" rel="thumbnail"><img border="0" src="http://www.hzmangel.info/blog/wp-content/uploads/2011/07/DSC_5853.png" width="580" height="485" /></a></div>
<h2>遗珠</h2>
<p>还有些片子不好归类，就都丢这吧~</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:8747F07C-CDE8-481f-B0DF-C6CFD074BF67:bb850698-5e26-4442-a616-0892ead68305" class="wlWriterEditableSmartContent"><a href="http://www.hzmangel.info/blog/wp-content/uploads/2011/07/DSC_5544-8x6.jpg" title="大风车吱呀吱悠悠的转" rel="thumbnail"><img border="0" src="http://www.hzmangel.info/blog/wp-content/uploads/2011/07/DSC_5544.png" width="455" height="610" /></a></div>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:8747F07C-CDE8-481f-B0DF-C6CFD074BF67:1de43d8e-4d09-4212-99aa-1f976dc15817" class="wlWriterEditableSmartContent"><a href="http://www.hzmangel.info/blog/wp-content/uploads/2011/07/DSC_5588-8x6.jpg" title="虽然只有一截，但也掩盖不了它彩虹的本质" rel="thumbnail"><img border="0" src="http://www.hzmangel.info/blog/wp-content/uploads/2011/07/DSC_5588.png" width="580" height="485" /></a></div>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:8747F07C-CDE8-481f-B0DF-C6CFD074BF67:06be7cca-af74-43b4-ba9d-4e7e3e112ae6" class="wlWriterEditableSmartContent"><a href="http://www.hzmangel.info/blog/wp-content/uploads/2011/07/DSC_5874-8x6.jpg" title="彩旗飘扬的百草敖包" rel="thumbnail"><img border="0" src="http://www.hzmangel.info/blog/wp-content/uploads/2011/07/DSC_5874.png" width="580" height="485" /></a></div>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:8747F07C-CDE8-481f-B0DF-C6CFD074BF67:fd79c031-febf-4636-b1f1-ea5c683e3759" class="wlWriterEditableSmartContent"><a href="http://www.hzmangel.info/blog/wp-content/uploads/2011/07/DSC_5898-8x6.jpg" title="超广角的天，是放毒的天" rel="thumbnail"><img border="0" src="http://www.hzmangel.info/blog/wp-content/uploads/2011/07/DSC_5898.png" width="580" height="485" /></a></div>
<p>&#160;</p>
<h2><font color="#ff0000">吐槽</font></h2>
<p>照片发放完毕，下面进入本文最后一个环节：吐槽~~~</p>
<ul>
<li>食：这次是我吃过的最难吃的农家饭，没有之一。先不说味道，以前吃的饭好歹能有一个硬点的菜，这次到好，除了那个烤全羊（这个后面专门吐槽），就没见到过能当作肉块的东西。那家的豆腐和南瓜味道倒是不错，不过我估计是个农家乐都能做出来这玩意，而且还比TA家的好吃。     </li>
<li>住：住过的最没有性价比的农家，同样没有之一。据说100一间一晚的标间，窗户直接通到院子还锁不上，屋里没有空调（第二天听到隔壁有一家几口晚上睡觉被冻的嗞哇乱叫在那和老板掐），热水器基本没出来过热水，水龙头的水是用来滴水穿石的。嗯，住的地方叫<strong><font color="#ff0000">金塞山庄</font></strong>，好像还是跟车导游家老姨开的，可以直接拉黑了（后面还要拉黑一个），嗯。      </li>
<li>黑：那边真TMD的黑啊：     <br />草地摩托100一小时，想去年去丰宁的时候也就40。CPI再涨也不带这么玩的。      <br />第一天晚上在外面找了家店吃烤全羊，店里面（还不是超市）18一瓶的酒能卖到70。      <br />住的地方给的烤全羊居然TMD是挂炉烤的，一点烟火味都没有，真不如白煮，羊杂做汤还要单独收钱。上烤全羊那天晚上先上一堆米饭馒头      <br />晚上说有篝火，随便拿了十来根树枝往竖的铁棍子上一靠，浇点汽油，那火是大，不到20分钟就点的连火都烤不成了。      <br />第三天早上包的小面看日出，给带到的地方烂不说，还开口要350，那点路在北京顶多60出头。      <br />景点骑马50一小时还是人牵着遛的，关键是那人还是走着牵着马，这哪是骑马啊，是明明是遛人有木有。      <br />跟车的那个导游啥事不干就会跟着车跑，然后到地方说一声到哪了留多少时间就不见影子了，最多会介绍一下这边哪家店是他哪个亲戚开的，然后后面此地无银的加上一句不鼓励大家乱购物哈….      </li>
<li>景：最想吐槽的就是这个，去之前听人说的天花乱坠地涌金莲说那有多么好看，号称风景最美的坝上，结果到了那边大失所望。这TM哪是草原啊，之前去丰宁那次我还以为我没看到那边所谓的京北第一草原，结果到了这号称风景最好的坝上才发现，坝上和草原放一起说的时候，人们省略了两个定语和一个连词，其实它的全称是河北的坝上和内蒙的草原……最不能忍的是那边晚上居然看不见星星，本来带着架子是想去拍银河的，结果连找个北斗都要维持45度仰望天空的姿势10秒以上才能看见，帝都大风天的晚上看到的星星也比这多啊。还有那些神马还珠格格康熙王朝外景地，到了那边直接吐槽无力了。</li>
</ul>
<p>差不多就这些了吧，该说的都说了，反正归到最后一句话就是如果没去过草原千万不要把第一次给坝上啊。以后想骑马骑摩托的直接去丰宁，离北京也近。想看景色的再多跑点至少去锡盟吧，300多公里都开出来了也不再多这100来公里，况且到赤峰还有火车，当然呼伦贝尔或青海或西藏会更好。对于我来说，估计以后会把坝上直接拉黑了吧（第二个被拉黑的登场），因为相比于骑马，我还是更愿意看风景吧，而坝上的风景，唔，吐槽无力了~~</p>

<p><a href="http://feedads.g.doubleclick.net/~a/lHQV8QqGCCu5JILiFmgc6Qs80kM/0/da"><img src="http://feedads.g.doubleclick.net/~a/lHQV8QqGCCu5JILiFmgc6Qs80kM/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/lHQV8QqGCCu5JILiFmgc6Qs80kM/1/da"><img src="http://feedads.g.doubleclick.net/~a/lHQV8QqGCCu5JILiFmgc6Qs80kM/1/di" border="0" ismap="true"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.hzmangel.info/blog/archives/1031/feed</wfw:commentRss>
		<slash:comments>26</slash:comments>
		<feedburner:origLink>http://www.hzmangel.info/blog/archives/1031</feedburner:origLink></item>
		<item>
		<title>Remove packages installed by setup.py install</title>
		<link>http://feedproxy.google.com/~r/hzmangel/~3/1vd3e866Yrg/999</link>
		<comments>http://www.hzmangel.info/blog/archives/999#comments</comments>
		<pubDate>Sat, 02 Jul 2011 17:27:23 +0000</pubDate>
		<dc:creator>hzmangel</dc:creator>
				<category><![CDATA[小企鹅Linux]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.hzmangel.info/blog/archives/999</guid>
		<description><![CDATA[从源码装了个Python程序的包结果发现系统的仓库中有，于是想先把源码装的包删除了再去装仓库中的，可惜setup.py没有uninstall参数，于是改问G神，在stackoverflow上找到了折衷的办法：先用install把包重新装一遍，装的时候记录下文件的改动，然后去把它们统统删除，唔，好囧的办法。 $ python setup.py install --record foo.txt $ cat foo.txt &#124; xargs rm -f 没找到怎么让它输出到stdout，只好用临时文件弄了。]]></description>
			<content:encoded><![CDATA[<p>从源码装了个Python程序的包结果发现系统的仓库中有，于是想先把源码装的包删除了再去装仓库中的，可惜setup.py没有uninstall参数，于是改问G神，在stackoverflow上找到了<a href="http://stackoverflow.com/questions/1550226/python-setup-py-uninstall" target="_blank">折衷的办法</a>：先用install把包重新装一遍，装的时候记录下文件的改动，然后去把它们统统删除，唔，好囧的办法。</p>
<pre class="brush: bash">
$ python setup.py install --record foo.txt
$ cat foo.txt | xargs rm -f
</pre>
<p>没找到怎么让它输出到stdout，只好用临时文件弄了。</p>

<p><a href="http://feedads.g.doubleclick.net/~a/ktei456TgeN6miR1LDRiRxlI8Jo/0/da"><img src="http://feedads.g.doubleclick.net/~a/ktei456TgeN6miR1LDRiRxlI8Jo/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/ktei456TgeN6miR1LDRiRxlI8Jo/1/da"><img src="http://feedads.g.doubleclick.net/~a/ktei456TgeN6miR1LDRiRxlI8Jo/1/di" border="0" ismap="true"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.hzmangel.info/blog/archives/999/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://www.hzmangel.info/blog/archives/999</feedburner:origLink></item>
	</channel>
</rss>

