論盡蛋
心で書く

Blog


Frontend fragment caching

Today added fragment caching in frontend, including posts, user profiles, and portfolio entries.

Before the fragment caching, rendering a post takes these steps:

  1. retrieve the object(s) from database
  2. parse the markdown content to HTML output
  3. just output those meta (author, tags, etc) and the content

But now, the above would only do normally 1 time only. Although the cache that are too old might be deleted due to the memory limit of the memcache store.

The 2nd time and later, just the cached HTML fragments would be returned (hopefully from memory). However, the retrieval of the posts is still required in order to check if there are any updates. But less time is used for retrieving the tags, translations, and rendering the partials.

*[HTML]: HyperText Markup Language


Up coming changes of this site

Haha it is actually a little bit strange to disclose the details of the models here, especially the same site's own models XD"

Currently we have 3 different models for "articles": Post, Page and Entry (entry is inside portfolio).

However, (intentionally) these 3 models shares 99.99% (ok, actually not mathematically calculated) the same attributes and behaviours:

  • translatable title and content
  • URL slugging (with friendly_id gem)
  • published_at handling in admin panel
  • preview in frontend
  • tags, comments, sharing

and even the frontend interface for these 3 things are extremely similar.

Actually I do intentionally to make them the same. It is because I do feel they should be the same. And now I'm right.

And even worse (or better??), I now am adding two more models: board games and coupons. And I found they could have the completely the same things too.

So...is it worth to group them together?

Now board games and coupons are subclasses of CollectionItem, which have the same attributes as post and page.

However, Coupon have more attributes than that, e.g. expired_at. So There is a CouponInfo model having 1-to-1 relationship to Coupon model.

It's actually good for me. And so now I can do something I wanted to do:

Currently this great responsive theme is not designed by me (you may fork the originally version in here, which was designed for Octopress).

The theme is great. However I do want a self-designed theme for my own blog.

Now I think it is the time ;)

I would do these 3 steps to do so:

  1. existing data migration
    • remember the translated versions
    • entry has an extra homepage attribute (that means there should be an EntryInfo model)
  2. delete old tables (backing up the database is a common sense)
  3. change the existing model to subclass from collection item
  4. run test cases again to confirm working

Unknown Heroku pull not working

According to this article, we can use heroku pull to export data from heroku's db to local db.

(Pulling my blog's posts down for the test of changing markdown engine)

However, I am getting this error:

!    Taps Load Error: cannot load such file -- taps/operation
!    You may need to install or update the taps gem to use db commands.
!    On most systems this will be:
!
!    sudo gem install taps

OK, it asked me to install taps, so I ran gem install taps (without sudo intendedly).

Then I ran again heroku pull, now a slightly different error occurred:

!    Taps Load Error: cannot load such file -- sqlite3
!    You may need to install or update the taps gem to use db commands.
!    On most systems this will be:
!
!    sudo gem install taps

What? install taps again..? But you mentioned cannot load sqlite3. I didn't use sqlite3 in this project, maybe taps internally uses sqlite3? OK, I try to install sqlite3 with gem install sqlite3.

Finally heroku pull works.


My Apache + Pow.cx setup

I use Mac OS X, which have Apache2 installed by default. On the other hand, Pow.cx is great for running Rails apps locally (and with the new .xip.io for other computers to access).

So this is a post for myself, to jot down notes on how to set these up.

Basically just follow this wiki.

After following the above wiki (Running Pow with Apache), all things should be ready now.

To create a rails app

Given ~/Projects/rails-app.

When you create a symbolic link in the ~/.pow directory.

#!bash
cd ~/.pow
ln -s ~/Projects/rails-app

Then you should be able to visit the rails app through http://rails-app.dev.

Renaming ~/.pow/rails-app could change the domain name.

To create a php app

Given ~/Projects/php-app

When you do these two things:

  1. edit /etc/hosts to add a host (e.g. 127.0.0.1 php-app.local)
  2. edit /private/etc/apache2/extra/httpd-vhosts.conf to add your virtual host (or the conf file you use to add virtual hosts)

    DocumentRoot "/Users/PeterWong/Projects/php-app" ServerName php-app.local Options Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews AllowOverride All Order allow,deny Allow from all

Then you should be able to access the site through http://php-app.local.


Drop PostgreSQL database

Update:

If you are using Rails 4.x, please read this. Thank you Manuel Meurer for letting me know the following implementation applies to Rails 3.x only.

If you are using Rails 3.x, you may continue use the following patch.


Some of my projects uses PostgreSQL as my database. However, running rake db:drop always gives me the following error:

Couldn't drop PROJECT_NAME_development : #<ActiveRecord::StatementInvalid: PG::Error: ERROR:  database "PROJECT_NAME_development" is being accessed by other users
DETAIL:  There are 2 other session(s) using the database.
: DROP DATABASE IF EXISTS "PROJECT_NAME_development">

To resolve this problem, as hinted by the message about, is to stop all sessions using that database.

However, I just found (I think) better solution from this stackoverflow answer (which points to this gist).

It is to monkey patch the rake db:drop command. To do so, simply copy the code into lib/tasks/databases.rake and now rake db:drop is patched with this code which stops the connections.

The code is as follow:

#!ruby #{Rails.root}/lib/tasks/databases.rake
=begin
  Monkey Patch 
  activerecord-3.0.9/lib/active_record/railties/databases.rake
  clears obstinate stale PG session to get parallel_tests working
  also, PG user must be superuser to use these low level PG functions
=end
def drop_database(config)
  case config['adapter']
  when /mysql/
    ActiveRecord::Base.establish_connection(config)
    ActiveRecord::Base.connection.drop_database config['database']
  when /sqlite/
    require 'pathname'
    path = Pathname.new(config['database'])
    file = path.absolute? ? path.to_s : File.join(Rails.root, path)

    FileUtils.rm(file)
  when /postgresql/
    ActiveRecord::Base.connection.select_all("select * from pg_stat_activity order by procpid;").each do |x|
      if config['database'] == x['datname'] && x['current_query'] =~ /<IDLE>/
        ActiveRecord::Base.connection.execute("select pg_terminate_backend(#{x['procpid']})")
      end
    end
    ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public'))
    ActiveRecord::Base.connection.drop_database config['database']
  end
end