标签: web

Kaminari 的 AJAX 翻页实现

Kaminari 是 rails 上一个很有名的分页管理扩展,使用极其简单。最近刚在项目中使用了它的 AJAX 分页的功能,记录一下实现的过程。

基本的安装和配置就不啰嗦了,按照官方的教程来进行就是啦,具体记录一下 AJAX 翻页实现的部分,以一个订单列表的页面作例子。

通过ActiveRecord访问数据表的列信息

ActiveRecord提供了很多方法来访问某个模型数据表的列信息

columns
返回一个列对象的数组

columns_hash
类似columns方法,不过返回一个以列名为key,列对象为value的hash数组

column_names
返回模型数据表列名的数组

Drupal字符截取函数views_trim_text

Drupal的Views模块有一个很好用的字符截取函数views_trim_text,它的用法如下:

views_trim_text($alter, $value)

参数:
$alter

  • max_length: 字符串最大长度,超出部分将被截取
  • word_boundary: 以单词(Word)为边界来截取
  • ellipsis: 以单词(Word)为边界来截取,结尾以‘...’结束
  • html: 确保html标签的完整性

mysql log-bin 日志文件

前段时间有人向我反映说我的VPS无法上传文件了,我登录上去一查,原来是VPS的磁盘空间已经差不多满了,FTP在可用空间少于10%的时候就拒绝上传文件了。当时因为工作忙,没有时间细查,只是把一些临时文件清理了让他不要再往网站上添加资料就放到一边了。今天记起这件事,怎么也想不明白平时的网页文件,应该占用不了这么多的空间的啊,到底是谁把我的空间吃掉了呢?

Rails3.1 invalid multibyte char错误处理

代码文件有中文字符,打开页面时报:invalid multibyte char (US-ASCII) 错误,造成这个错误是因为Ruby1.9默认用ASCII编码来读源码的,如果代码里有非ASCII字符,就会发生这个错误。解决的方法是在有非ASCII字符文件的首行指定encoding即可,如:

# encoding: utf-8
class ApplicationController < ActionController::Base
  protect_from_forgery
  ...........

话说每一个文件都要加是不是太麻烦点?就不能弄一个全局设定来吗?

Mysql乱码一例

前几天要把一个网站从服务器A转移到服务器B,原本以为这是一个很简单的事情,结果把网站程序复制过去之后,却发现有问题了:从数据库里读取出来的数据都变成乱码了!

初步认为是字符集的问题,但是看了导入的数据库的语句,都有指定了DEFAULT CHARSET=utf8,也没看出有什么问题啊。多次删除——重建——导入数据库结果都还是乱码,突然想到“会不会是建立数据库时默认的编码不同呢”? 马上输入sql命令查看:

mysql> show variables like 'char%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | latin1                     |
| character_set_connection | latin1                     |
| character_set_database   | latin1                     |
| character_set_filesystem | binary                     |
| character_set_results    | latin1                     |
| character_set_server     | latin1                     |
| character_set_system     | latin1                     |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)

果然默认的字符集是latin1,难怪使用utf8来读取的时候会出现乱码。知道原因就比较好办了,修改/etc/mysql/my.cnf在相应的位置添加以下内容:

[client]
default-character-set=utf8

[mysqld]
character-set-server = utf8

然后重启mysql服务就可以应用新的设置了:

/etc/init.d/mysql restart

查看结果:

mysql> show variables like 'char%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8                       |
| character_set_connection | utf8                       |
| character_set_database   | utf8                       |
| character_set_filesystem | binary                     |
| character_set_results    | utf8                       |
| character_set_server     | utf8                       |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.08 sec)

为什么同样是默认的配置(服务器A的mysql默认配置文件里也没有上面添加的那两条内容),在服务器A和服务器B的结果不一样呢,难道是因为两个服务器使用的发行版不同所以默认的参数也就不一样吗?(服务器A使用的Gentoo,服务器B使用的是Ubuntu)看来不同发行版会使用不同的默认参数这个问题以后要多多注意才行。

robots.txt 404错误的解决

最近查看网站日志,在404错误的条目里,出现最多的就是robots.txt这个文件了。原本以为是我真没有这个文件,但一检查发出根目录下是有这个文件的,但为什么还是显示page not found呢?然后我再以为是Drupal的问题,但是在网上搜索了好久,也没听说这个跟Drupal有什么关系。最后才突然想到可能是Nginx服务配置的问题,一查配置文件,果然是我没有加上txt文件支持的原因。

知道原因就好办了,在配置文件里加入下面几句就可以了:

location ~ (^\/|\.html|\.css|\.jpg|favicon\.ico|robots\.txt|\.png|\.js|\.gif)$ {
        root   /var/www/hosts/nofool.info/htdocs/;
        access_log        off;
        expires           30d;
}

上面的例子是为Nginx加入一些静态文件如html、css、jpg、png、js、gif的支持,txt文件则只支持robots.txt,ico文件则只支持favicon.ico

自动把网址转换超链接代码(PHP 版)

有时候需要在提交内容的时候,自动把一些网址自动加上超链接。下面是一个PHP的样例,支持转换普通的链接、FTP地址、E-mail地址、Twitter类的链接,里面的正则表达式稍作修改也可以用于其它的语言。

function add_links($text) {
    $text= preg_replace("/(^|[\s ])([\w]*?)((ht|f)tp(s)?:\/\/[\w]+[^ \,\"\n\r\t<]*)/is", "$1$2<a href=\"$3\" >$3</a>", $text); /* http[s]//** */
    $text= preg_replace("/(^|[\s ])([\w]*?)((www|ftp)\.[^ \,\"\t\n\r<]*)/is", "$1$2<a href=\"http://$3\" >$3</a>", $text); /* ftp://** */
    $text= preg_replace("/(^|[\n ])([a-z0-9&\-_\.]+?)@([\w\-]+\.([\w\-\.]+)+)/i", "$1<a href=\"mailto:$2@$3\">$2@$3</a>", $text); /* E-mail */
    $text= preg_replace("/@(\w+)/", '<a href="http://www.twitter.com/$1" target="_blank">@$1</a>', $text); /* @twitter 用户 */
    $text= preg_replace("/\#(\w+)/", '<a href="http://search.twitter.com/search?q=$1" target="_blank">#$1</a>',$text); /* #twitter 搜索 */
    return $text;
}

Nginx 通过FCGI支持Perl 脚本

折腾了几天,总算让Nginx也支持Perl程序了。因为之前已经配置好PHP的环境了(请看这里),所以这一次只是想在原来的的基础上增加Perl的支持而已,所以并不打算需要太复杂的设置。在网上找了很久,都没有找到比较好的教程,很多都需要自己写一个接口程序和启动脚本,并且很多都是不太符合Gentoo启动脚本的格式。最后没办法,只有自己慢慢的摸索了,参照PHP的相关设置,绕了不少的弯路,才总算成功了。趁自己还没有忘记之前,把过程记录下来吧。

首先,需要的是一个Perl的接口程序,找了好久我才找到了fcgiwrap这个程序,还好,Gentoo的Portage里也有,可以直接emerge它:

$ eix fcgiwrap
[*] www-misc/fcgiwrap
     Available versions:  (~)1.0.2-r1 (**)9999
     Installed versions:  1.0.2-r1(22时48分47秒 2010年08月05日)
     Homepage:            ht tp://nginx.localdomain.pl/wiki/FcgiWrap
     Description:         Simple FastCGI wrapper for CGI scripts (CGI support for nginx)
$ sudo emerge fcgiwrapp

创建一个spawn-fcgi启动脚本的链接

$ sudo ln -s /etc/init.d/spawn-fcgi  /etc/init.d/spawn-fcgi.pl

spawn-fcgi的配置文件

$ cat /etc/conf.d/spawn-fcgi.pl
# Copyright 1999-2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/www-servers/spawn-fcgi/files/spawn-fcgi.confd,v 1.6 2009/09/28 08:38:02 bangert Exp $

# DO NOT MODIFY THIS FILE DIRECTLY! CREATE A COPY AND MODIFY THAT INSTEAD!

# The FCGI process can be made available through a filesystem socket or
# through a inet socket. One and only one of the two types must be choosen.
# Default is the inet socket.

# The filename specified by
# FCGI_SOCKET will be suffixed with a number for each child process, for
# example, fcgi.socket-1. 
# Leave empty to use an IP socket (default). See below. Enabling this, 
# disables the IP socket.
# 
FCGI_SOCKET=/var/run/fcgiwrap.sock

# When using FCGI_PORT, connections will only be accepted from the following
# address. The default is 127.0.0.1. Use 0.0.0.0 to bind to all addresses.
#
#FCGI_ADDRESS=127.0.0.1

# The port specified by FCGI_PORT is the port used
# by the first child process. If this is set to 1234 then subsequent child
# processes will use 1235, 1236, etc.
#
FCGI_PORT=

# The path to your FastCGI application. These sometimes carry the .fcgi
# extension but not always. For PHP, you should usually point this to
# /usr/bin/php-cgi.
#
FCGI_PROGRAM=/usr/sbin/fcgiwrap

# The number of child processes to spawn. The default is 1.
#
#FCGI_CHILDREN=1

# If you want to run your application inside a chroot then specify the
# directory here. Leave this blank otherwise.
#
#FCGI_CHROOT=

# If you want to run your application from a specific directiory specify
# it here. Leave this blank otherwise.
#
#FCGI_CHDIR=

# The user and group to run your application as. If you do not specify these,
# the application will be run as root:root.
#
FCGI_USER=nginx
FCGI_GROUP=nginx

# Additional options you might want to pass to spawn-fcgi
#
FCGI_EXTRA_OPTIONS="-M 0700"

# If your application requires additional environment variables, you may
# specify them here. See PHP example below.
#
ALLOWED_ENV="PATH"

Nginx配置文件

$ cat /etc/nginx/vhosts/example.com.conf
server {
    listen 127.0.0.1;
    server_name *.example.com example.com;
    access_log /var/log/nginx/localhost.access_log main;
    error_log /var/log/nginx/localhost.error_log info;
    root /var/www/example.com;

    location ~ .*.php$ {
	include /etc/nginx/fastcgi.conf;
	fastcgi_pass 127.0.0.1:1234;
	fastcgi_param  SCRIPT_FILENAME  /var/www/example.com/$fastcgi_script_name;
	fastcgi_index index.php;
    }
    
    location ~ .*.pl$ {
	include /etc/nginx/fastcgi_params;
	fastcgi_pass unix:/var/run/fcgiwrap.sock-1;
	fastcgi_param  SCRIPT_FILENAME  /var/www/example.com/$fastcgi_script_name;
	fastcgi_index index.pl;
    }

这里要注意的是,网上很多教程和fcgiwrap的手册(man page)都是把fastcgi_pass设置成 fastcgi_pass unix:/var/run/fcgiwrap.sock ,但是这样是不行的,查看Nginx的Log会发现有提示如下的错误:

connect() to unix:/var/run/fcgiwrap.sock failed (2: No such file or directory) while connecting to upstream, client: 127.0.0.1, server: *.example.com, request: "GET /test.pl HTTP/1.1", upstream: "fastcgi://unix:/var/run/fcgiwrap.sock:", host: "example.com"

原因嘛,/etc/conf.d/spawn-fcgi.pl 这个配置文件里关于FCGI_SOCKET的注释有写到,FCGI_SOCKET会为每个子进程添加一个数字后缀,所以需要把这个后缀也要添加上去,例如: fastcgi_pass unix:/var/run/fcgiwrap.sock-1; 否则,就会出现文件找不到的错误,我在这里花了不少的时间才明白这个事情。

最后,启动相关服务:

$ sudo /etc/init.d/spawn-fcgi.pl start
$ sudo /etc/init.d/nginx start

如果还是出现502错语并且Nginx Log 里有这样的出错提示:

upstream closed prematurely FastCGI stdout while reading response header from upstream, client: 127.0.0.1, server: *.example.com, request: "GET /test.pl HTTP/1.1", upstream: "fastcgi://unix:/var/run/fcgiwrap.sock-1:", host: "example.com"

那就要检查一下你的Perl文件是否有读取跟执行的权限了(755),在这里又花了我很长的时间才明白Perl脚本是还需要执行的权限的,这一点跟PHP不同。