Rails应用添加配置的方法

方法一: 使用 app_config 插件

script/plugin install http://svn.jarmark.org/rails/app_config

Rails::Initializer.run do |config|
     ...
     config.app_config.hello = 'world'
     ...
end

程序中,则可以通过 AppConfig.hello 直接引用。

参考: http://jarmark.org/projects/app-config/

方法二:使用 application config
参考: http://agilewebdevelopment.com/plugins/application_config

方法三:通过全局变量

在config/initializers中新增文件 app_config.rb,内容为:

module ApplicationConfiguration
  require 'ostruct'
  require 'yaml'
  if File.exists?( File.join(RAILS_ROOT, 'config', 'application.yml') )
    file = File.join(RAILS_ROOT, 'config', 'application.yml')
    users_app_config = YAML.load_file file
  end

  ::AppConfig = OpenStruct.new users_app_config
end

然后,在config中增加application.yml,在里面以YML方式写入配置,比如:
hello: ‘world’

则,在程序中,可以直接引用: AppConfig.hello。也可以在程序中对配置项赋值,比如 AppConfig.hello = ‘cool’

page cache with dynamic content

在rails的3种cache策略page cache, action cache和fragment cache中, page cache无疑是最快的.它把控制完全地交给web server, 会在RAILS_ROOT/public/目录下生成缓存过的静态文件,绕过了rails的处理,自然速度飞快.在现实应用中,页面的内容不可能是纯静态的,通常还包含特定用户的信息,这样是不是就是说不能使用page cache了呢?当然不是.这时javascript就可以帮上忙了.
有两种处理方式:
1.先加载页面的大部分,然后使用 JavaScript 和 Ajax 加载该页面较小的动态部分。
在页面上发起一个ajax请求

new Ajax.Request(”/home/get_info”,
{asynchronous:true, evalScripts:true, method:’get’});

2.将某些用户状态(比如用户是否已登录)存储在客户端的 cookie 中。然后,根据 cookie 的内容,使用 JavaScript 动态更改页面的外观。
示例的javascript代码如下:
function handle_cached_user() {
var login_cookie = readCookie(’login’);
var logged_in = document.getElementById(’logged_in’);
var logged_out = document.getElementById(’logged_out’);
if(login_cookie == null) {
logged_in.style.display = ‘none’;
logged_out.style.display = ‘block’;
} else {
logged_out.style.display = ‘none’;
logged_in.style.display = ‘block’;
}
}

上述两种方式的比较.前者取得少量dynamic content的ajax调用还是会牵涉到rails, 后者则完全和rails无关,速度更快,其缺点是页面上的javascript有时会过于复杂,难以管理,而且不能在cookie中存储敏感信息.前者更为灵活,虽然还是会牵涉到rails, 但是在dynamic content只占页面总数据量的比例很小时,仍能借此得到不小的性能提升.

generate db schema for rails

1. 首先要下载以下两个文件。
* uml_dumper.rb. 下载地址: http://blog.zmok.net/files/uml_dumper.rb
* uml.rake. 下载地址:http://blog.zmok.net/files/uml.rake
下载完成之后将uml_dumper.rb放到Rails工程的Lib目录中,将uml.rake放到Rails工程的Lib/tasks目录中.

2. 生成包含数据库结构的XML文件。
*运行 rake uml:schema
这样会在工程的 db 目录中生成 schema.xml 文件

3. 安装starUML
*starUML是一个开源的UML工具。下载地址:http://staruml.sourceforge.net/en/download.php

4. 生成数据库结构图。

*运行 staruml,新建工程,file - import - xmi,导入刚才生成的schema.xml 文件,在 Model Exploerer 中就可以看到生成的图了.

5. 自动排列结构图,并导出JPG格式的图片。

*右键 - format - Layout diagram, 自动排列结构图
*file - Export diagram, 导出图片格式的结构图

in_place_editor for rails2.0.2

in_place_editor使用:


script/plugin install in_place_editing

# Controller
class BlogController < ApplicationController
  in_place_edit_for :post, :title
end

# View
<%= in_place_editor_field :post, 'title' %>

在rails2.0及以上版本使用时,出现如下错误:
ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken)

解决办法
修改 vendor/plugins/in_place_editing/lib/in_place_macros_helper.rb


42a43,46
>     if protect_against_forgery?
>       options[:with] ||= "Form.serialize(form)"
>       options[:with] += " + '&authenticity_token=' + encodeURIComponent('#{form_authenticity_token}')"
>     end
53c57,58
     # js_options['evalScripts'] = options[:script] if options[:script]
>     js_options['htmlResponse'] = !options[:script] if options[:script]
55a61
>     js_options['textBetweenControls'] = %('#{options[:text_between_controls]}') if options[:text_between_controls]

修改后的文件为 http://cookbook.enjoyrails.com/cookbooks/20

参考:
http://dev.rubyonrails.org/attachment/ticket/10055/in_place_editing_should_work_with_csrf_and_rjs.patch

ultrasphinx step by step

    ultrasphinx是基于sphinx的rails全文搜索插件。我们将在一个已有的博客系统上增加全文搜索来学习这个插件,

1. 首先确保系统已经安装以下软件:
* MySQL 5.0
* Sphinx 0.9.8-dev r1112
* Rails 2.0.2
并且需要安装chronic gem,rails应用使用的是mysql数据库

2. 安装插件:
$script/plugin install -x svn://rubyforge.org/var/svn/fauna/ultrasphinx/trunk
$mkdir config/ultrasphinx
$cp vendor/plugin/ultrasphinx/examples/default.base config/ultrasphinx/

3. 标记需要索引的内容:
#app/models/post.rb
is_indexed :fields => [”title”, “body”]

#app/models/comment.rb
is_indexed :fields => [”body”]

4. 多model的统计配置:
#config/initializers/ultrasphinx
Ultrasphinx::Search.client_options[:with_subtotals] = true

5. 生成索引,并运行ultrasphinx:
$rake ultrasphinx:configure
$sudo rake ultrasphinx:index
$sudo rake ultrasphinx:daemon:start

6.增加search controller:
$script/generate controller search

#app/controllers/search_controller.rb
class SearchController < ApplicationController
  def index
    @search = Ultrasphinx::Search.new(:query => params[:q],
                                      :class_names => SearchHelper::class_name(params[:category]),
                                      :page => params[:page]|| 1)
    @search.run
  end
end
#app/helpers/search_helper.rb
module SearchHelper
  def output_results(search)
    stat = "搜索结果:"
    search.results.each do |result|
      stat << (render :partial => "#{result.class.to_s.downcase}", :object => result)
    end

    stat << "共 " << search.total_entries.to_s << "条结果。”

    search.subtotals.each do |category, count|
      stat << SearchHelper::ui_name(category) << “: ” << count.to_s << ” 条结果\t”
    end
    stat
  end

  def self.class_name(category_value)
    r = SEARCH_CATEGORIES.detect do |c|
      c[2] == category_value
    end || SEARCH_CATEGORIES[0]
    r[1]
  end

  def self.ui_name(class_name)
    r = SEARCH_CATEGORIES.detect do |c|
      c[1] == class_name
    end || SEARCH_CATEGORIES[0]
    r[0]
  end

  SEARCH_CATEGORIES = [
    #uiname, classname, uivalue
    [’所有’, nil, ‘all’],
    [’文章’, ‘Post’, ‘post’],
    [’评论’, ‘Comment’, ‘comment’]
  ].freeze
end
7. 提供搜索页面和搜索结果显示页面:
#app/views/shared/_search.html.erb
<form action="/search" method="get" id="search_form">
  <label for="search_category">\u7c7b\u522b\uff1a</label>
  <select id="search_category" name="category">
    <option value="all" selected="selected">\u6240\u6709</option>
    <option value="post">\u6587\u7ae0</option>
    <option value="comment">\u8bc4\u8bba</option>
  </select>
  <label for="q">\u5173\u952e\u5b57\uff1a</label>
  <input type="text" name="q" value="<%= params[:q] %>" id="q">
  <input type="submit" value="\u641c\u7d22">
</form>

#app/views/search/_post.html.erb
<div>
  文章:<%= post.title %><br />
  <%= truncate(post.body, 30) %>
</div>

#app/views/search/_comment.html.erb
<div>
  评论:
  <%= truncate(comment.body, 30) %>
</div>

#app/views/search/index.html.erb
<%= output_results(@search) %>
<%= will_paginate(@search) %>
Blog_1204988247420
8. 中文支持:
#config/ultrasphinx/default.base
ngram_len = 1
ngram_chars = U+4E00..U+9FBB, U+3400..U+4DB5, U+20000..U+2A6D6, U+FA0E, U+FA0F, U+FA11, U+FA13, U+FA14, U+FA1F, U+FA21, U+FA23, U+FA24, U+FA27, U+FA28, U+FA29,     U+3105..U+312C, U+31A0..U+31B7, U+3041, U+3043, U+3045, U+3047, U+3049, U+304B, U+304D, U+304F, U+3051, U+3053, U+3055, U+3057, U+3059, U+305B, U+305D, U+305F, U+3061,     U+3063, U+3066, U+3068, U+306A..U+306F, U+3072, U+3075, U+3078, U+307B, U+307E..U+3083, U+3085, U+3087, U+3089..U+308E, U+3090..U+3093, U+30A1, U+30A3, U+30A5, U+30A7,     U+30A9, U+30AD, U+30AF, U+30B3, U+30B5, U+30BB, U+30BD, U+30BF, U+30C1, U+30C3, U+30C4, U+30C6, U+30CA, U+30CB, U+30CD, U+30CE, U+30DE, U+30DF, U+30E1, U+30E2, U+30E3,     U+30E5, U+30E7, U+30EE, U+30F0..U+30F3, U+30F5, U+30F6, U+31F0, U+31F1, U+31F2, U+31F3, U+31F4, U+31F5, U+31F6, U+31F7, U+31F8, U+31F9, U+31FA, U+31FB, U+31FC, U+31FD,     U+31FE, U+31FF, U+AC00..U+D7A3, U+1100..U+1159, U+1161..U+11A2, U+11A8..U+11F9, U+A000..U+A48C, U+A492..U+A4C6
9. 重新索引和服务:
$rake ultrasphinx:configure
$sudo rake ultrasphinx:index
$sudo rake ultrasphinx:daemon:restart
Blog_1204988838430
    以上测试环境是:Ruby 1.8.6 + Rails 2.0.2,源代码下载地址:http://flyerhzm.googlepages.com/test_ultrasphinx.zip

MiniMagick for FileColumn

file_column用于图片上传、缩放非常方便,比如在系统中做用户头像之类。

但file_column默认使用rmagick来做图象处理。在实际使用过程中,发现rmagick有内存泄露问题,所以,将file_column中的图象缩放改为 mini_magick

在安装 file_column 后,只需要修改 vendor/plugins/file_column/lib/magick_file_column.rb。改动如下(完整代码请参考 http://cookbook.enjoyrails.com/cookbooks/9):


7,8c7,8
< img = ::Magick::Image::read(absolute_path).first
< rescue ::Magick::ImageMagickError
---
> img = ::MiniMagick::Image::from_file(absolute_path)
> rescue ::MiniMagick::MiniMagickError
38c38
< ::Magick
---
> ::MiniMagick
40c40
< require 'RMagick'
---
> require 'mini_magick'
51,52c51,52
< img = ::Magick::Image::read(absolute_path).first
< rescue ::Magick::ImageMagickError
---
> img = ::MiniMagick::Image::from_file(absolute_path)
> rescue ::MiniMagick::MiniMagickError
86a87,89
>
> img.combine_options do | i |
>
90,91c93,94
< img = img.crop(::Magick::CenterGravity, [img.columns, w].min,
< [img.rows, h].min, true)
---
> i.gravity "Center"
> i.crop "#{[img.columns, w].min}x#{[img.rows, h].min}"
95,97c98
< img = img.change_geometry(img_options[:size]) do |c, r, i|
< i.resize(c, r)
< end
---
> i.resize img_options[:size]
98a100,104
>
> i.strip # strip unnecessary profiles
> i.depth 8 # otherwise PNG bloats, big time
> i.quality 80 # save with reasonable quality for a thumbnail
> end
100,106c106
< img.write(dest_path) do
< if img_options[:attributes]
< img_options[:attributes].each_pair do |property, value|
< self.send "#{property}=", value
< end
< end
< end
---
> img.write(dest_path) #do
208c208
< require 'RMagick'
---
> require 'mini_magick'
				

auto_complete

Rails插件形式的Ajax.AutoCompleter实现

安装:

script/plugin install http://svn.rubyonrails.org/rails/plugins/auto_complete/

使用:

# Controller
class BlogController < ApplicationController
  auto_complete_for :tag, :name
end
# View<%= text_field_with_auto_complete :tag, name %>

参数介绍:

# Controller中可带参数有:conditions, :limit, :order
class BlogController < ApplicationController
  auto_complete_for :tag, :name, :limit => 15, :order => 'created_at DESC'
end
# View中可带参数有两种:一是tag_options,与text_field的options相同;
# 二是completion_options,与prototype库的Ajax.AutoCompleter的options相同
<%= text_field_with_auto_complete :tag, :name, {:size => 10}, {:tokens => ' '} %>

扩展:
auto_complete在输入框为空时,不会做任何事,如果你希望输入框为空时,也会去查询相应的数据完成complete的话,就需要修改一下源码:

# auto_complete.rbdef auto_complete_for(object, method, options = {})
  define_method("auto_complete_for_#{object}_#{method}") do
    if params[object].nil?
      find_options = {
        :order => "#{method} ASC",
        :limit => 10 }.merge!(options)
    else
       find_options = {
         :conditions => [ "LOWER(#{method}) LIKE ?", '%' + params[object][method] + '%' ],
         :order => "#{method} ASC",
         :limit => 10 }.merge!(options)
    end

    @items = object.to_s.camelize.constantize.find(:all, find_options)

    render :inline => "<%= auto_complete_result @items, '#{method}' %>"
  end
end
# View<%= text_field_with_auto_complete :tag, :name, {:onfocus => "tag_name_auto_completer.activate()"}, { :tokens => ' ' } %>

效果图:



使用Ultrasphinx实现多Model搜索

Sphinx是由俄罗斯(让人想起了Nginx:)人Andrew开发的全文搜索引擎。Ultrasphinx则是一个使用该引擎的Rails插件。本文介绍如何使用Ultrasphinx使用多Model搜索。

系统环境:

  • Leopard 10.5.2
  • MySql 5.0.45
  • Rails 2.0.2

注:Linux与之类似。Win平台需选择安装Sphinx的windows版本。

安装

  1. 安装mysql-devel
  2. 下载Sphinx 0.9.8源码,解压后安装:
     ./configure
    make
    sudo make install
  3. 安装chronic gem:
    sudo gem install chronic
  4. 安装Ultrasphinx:
    script/plugin install svn://rubyforge.org/var/svn/fauna/ultrasphinx/trunk

配置

将vender/plugins/ultrasphinx/examples/default.base拷贝至/config/ultrasphinx/default.base。为了支持中文,修改该文件,加上以下参数:

ngram_len = 1

ngram_chars = U+4E00..U+9FBB, U+3400..U+4DB5, U+20000..U+2A6D6, U+FA0E, U+FA0F, U+FA11, U+FA13, U+FA14, U+FA1F, U+FA21, U+FA23, U+FA24, U+FA27, U+FA28, U+FA29, U+3105..U+312C, U+31A0..U+31B7, U+3041, U+3043, U+3045, U+3047, U+3049, U+304B, U+304D, U+304F, U+3051, U+3053, U+3055, U+3057, U+3059, U+305B, U+305D, U+305F, U+3061, U+3063, U+3066, U+3068, U+306A..U+306F, U+3072, U+3075, U+3078, U+307B, U+307E..U+3083, U+3085, U+3087, U+3089..U+308E, U+3090..U+3093, U+30A1, U+30A3, U+30A5, U+30A7, U+30A9, U+30AD, U+30AF, U+30B3, U+30B5, U+30BB, U+30BD, U+30BF, U+30C1, U+30C3, U+30C4, U+30C6, U+30CA, U+30CB, U+30CD, U+30CE, U+30DE, U+30DF, U+30E1, U+30E2, U+30E3, U+30E5, U+30E7, U+30EE, U+30F0..U+30F3, U+30F5, U+30F6, U+31F0, U+31F1, U+31F2, U+31F3, U+31F4, U+31F5, U+31F6, U+31F7, U+31F8, U+31F9, U+31FA, U+31FB, U+31FC, U+31FD, U+31FE, U+31FF, U+AC00..U+D7A3, U+1100..U+1159, U+1161..U+11A2, U+11A8..U+11F9, U+A000..U+A48C, U+A492..U+A4C6

由于我们要对多个Model进行搜索,并且希望能得到每个Model的结果统计,需要对 Ultrasphinx进行额外的配置。在config/initializers下添加ultrasphinx.rb文件,内容如下:

Ultrasphinx::Search.client_options[:with_subtotals] = true

实现

假设我们有两个Model需要支持搜索,一个为Post,一个为User,Post需要搜索title属性,User需要搜索name属性。在Post类里加上:

is_indexed :fields => ['title']

在User类里加上:

is_indexed :fields => ['name']

Ultrasphinx提供了几个rake任务来管理索引和索引服务。首先,用以下任务来生成配置文件(在default.base基础上根据加上了is_indexed方法的Model自动生成配置);生成的配置文件也位于config/ultrasphinx目录,名称为[RAILS_ENV].conf,比方说development环境下生成的是development.conf:

rake ultrasphinx:configure

接下来,生成索引:

rake ultrasphinx:index

完成后(非常快),启动索引服务:

rake ultrasphinx:daemon:start

一切准备妥当,可以来实现搜索功能了。以SearchController为例,在其index action中实现如下逻辑:

class SearchController < ApplicationController
def index
  @search = Ultrasphinx::Search.new(
    :query => params[:q],
    :class_names => SearchHelper::class_name(params[:category]),
    :page => params[:page] || 1
    )
  @search.run
end

end

index.html.erb视图如下:

<%= output_results(@search) %>
<%= will_paginate(@search) %>

你可能已经注意到了,是的,Ultrasphinx可以跟will_paginate无缝集成,cool!

Ultrasphinx::Search.new方法中,传入的:query参数是查询关键字,:class_names是一个数组或字符串,指定要查询的Model类。我们在 SearchHelper中实现class_name方法来判断用户要查询的Model类,实现output_results方法来输出查询结果:

module SearchHelper
def output_results(search)
  stat = "搜索结果:"
  search.results.each do |result|
    stat << (render :partial => "/search/#{result.class.to_s.downcase}", :object => result)
  end

  stat << '共 ' << search.total_entries.to_s << ' 条结果。'

  search.subtotals.each do |category, count|
    stat << SearchHelper::ui_name(category) << ':' << count.to_s << " 条结果\t"
  end
  stat
end

def self.class_name(category_value)
  SEARCH_CATEGORIES.detect do |c|
    c[2] == category_value
  end[1]
end

def self.ui_name(class_name)
  SEARCH_CATEGORIES.detect do |c|
    c[1] == class_name
  end[0]
end

SEARCH_CATEGORIES = [
# uiname, classname, uivalue
['所有', nil, 'all'],
['文章', 'Post', 'post'],
['用户', 'User', 'user']    ].freeze
end

另外,我们在页面上提供一个搜索表单给用户,让他可以选择搜索文章、用户,还是所有内容:

<form action=”/search” method=”get” id=”search_form”>
<label for=”search_category”>类别:</label>
<select id=”search_category” name=”category”></select><label for=”q”>关键字:</label>
<input name=”q” value=”<%= params[:q] %>” id=”q” type=”text” />

<input value=”搜索” type=”submit” />

</form>

最后,把_post.html.erb和_user.html.erb这两个视图文件扔到search的视图目录下。里面加上显示一条相关Model的搜索结果的展示即可。

结论:

通过Ultrasphinx插件,非常容易实现多Model全文搜索。其要点是:

  • 使用Ultrasphinx::Search.new生成search对象时使用class_names参数指定要搜索的Model的名称(或使用nil值指定搜索所有Model);
  • 设定Ultrasphinx::Search.client_options[:with_subtotals] = true以支持各Model搜索结果的统计,并使用搜索结果的subtotals hash获取这些统计;
  • 加上ngram_chars和ngram_len参数,以支持中文搜索(同时需保证MySql数据表使用utf8编码)。

Memcached+Rails

本文介绍了Memcached在rails中的应用,内容涵盖memcached介绍、安装,在rails中的配置,具体使用的例子。

测试环境为Ubuntu7.10 + Rails2.0.1 + MySQL5.0.45 + Memcached 1.2.4

介绍
memcached是一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨大的hash表,它能够用来存储各种格式的数据,包括图像、视频、文件以及数据库检索的结果等。最初为了加速 LiveJournal 访问速度而开发的,后来被很多大型的网站采用。起初作者编写它可能是为了提高动态网页应用,为了减轻数据库检索的压力,来做的这个缓存系统。它的缓存是一种分布式的,也就是可以允许不同主机上的多个用户同时访问这个缓存系统, 这种方法不仅解决了共享内存只能是单机的弊端, 同时也解决了数据库检索的压力,最大的优点是提高了访问获取数据的速度!基于memcached作者对分布式cache的理解和解决方案。memcached官方站点

安装
memcached安装过程

wget http://www.danga.com/memcached/dist/memcached-1.2.4.tar.gz
tar -xzvf memcached-1.2.4.tar.gz
sudo ./configure checking for libevent directory... configure: error: libevent is required.  You can get it from http://www.monkey.org/~provos/libevent/ 

If it's already installed, specify its path using --with-libevent=/dir/ 

cd .. 

wget http://www.monkey.org/~provos/libevent-1.3e.tar.gz 

tar xzvf libevent-1.3e.tar.gz 

sudo ./configure && sudo make && sudo make install 

sudo gem install memcache-client 

$ memcached --help
memcached: error while loading shared libraries: libevent-1.3e.so.1: cannot open shared object file: No such file or directory 

ln -s /usr/local/lib/libevent-1.3e.so.1 /lib/ 

memcached -d -m 48 -l 127.0.0.1 -p 11211

cached_model安装

sudo gem install cached_model

cached_model是用来缓存单条纪录的,依赖于memcache-client,安装的同时也会把memcache-client装上,如果不缓存单条纪录,应该可以不装cached_model,具体我没有试过。
rails中的配置
配置environment.rb


require 'cached_model'
memcache_options = {
:c_threshold => 10_000,
:compression => true,
:debug => false,
:namespace => 'my_rails_app',
:readonly => false,
:urlencode => false
} 

CACHE = MemCache.new memcache_options
CACHE.servers = ['localhost:11211', 'localhost:11212'] #这里我启动了两个memcached server

这里的文档,好像options只有:namespace, :readonly, :multithread

具体使用
设置session storage为memcachedenvironment.rb中做如下修改:

# config.action_controller.session_store = :active_record_store
config.action_controller.session_store = :mem_cache_store

自动缓存model

参考的很多资料像下面这么说,但是在我的环境下没有成功,我也把步骤整理在这

*将需要缓存的model由原来继承自ActiveRecord::Base改为继承自CachedModel?

class Foo < CachedModel
end

*运行console

>>Foo.find 1
=>MemCache Get (0.134546)  active_record:Foo:1
=> SELECT * FROM foos WHERE (foos.id = 1) LIMIT 1
=>MemCache Set (0.024758)  active_record:Foo:1 >>Foo.find 1
=>MemCache Get (0.032337)  active_record:Foo:1
手动缓存
require 'md5'
k = MD5.new("sql condition here")
qs = Cache.get k
if qs.blank?
	puts "===============================no cached"
	qs = Foo.find(:all, :conditions => "sql condition here")
	Cache.put k, qs, 60*30 #expire after 30min
end

我在qs = Cache.get k这一行出现了undifined module/class :Foo这样的异常,在get的时候会执行 Marshal.load, 找不到Foo类,google之后,在前面调用Foo.class先载入Foo class后消除异常。

参考
memcached官方站点
Memcached Basics for Rails
Memcachedb,新浪发起的开源软件项目

Unobtrusive Javascript Date-Picker

这是一款日历选择插件

安装:

script/plugin install http://rails-unobtrusive-date-picker.googlecode.com/svn/trunk/unobtrusive_date_picker/

引用:

<%= javascript_include_tag "datepicker" %>

<%= stylesheet_link_tag "datepicker" %>

使用:

<% form_for :article, :url => { :action => @form_action, :id => @article } do |f| {

    Date: <%= f.unobtrusive_datetime_picker :date >

<% end %>

汉化:
在/public/javascript/lang/下创建cn.js

var fdLocale = {

        months:[

                "一月",

                "二月",

                "三月",

                "四月",

                "五月",

                "六月",

                "七月",

                "八月",

                "九月",

                "十月",

                "十一月",

                "十二月"

                ],

        fullDay:[

                "星期一",

                "星期二",

                "星期三",

                "星期四",

                "星期五",

                "星期六",

                "星期日"

                ],

        /* Only stipulate the dayAbbr should the first letter of the fullDay not suffice        dayAbbr:[],

        */

/* Only stipulate the firstDayOfWeek should the first day not be Monday

firstDayOfWeek:0,

        */

        titles:[

                "上一月",

                "下一月",

                "上一年",

                "下一年",

                "今天",

                "显示日历"

                ]

};

在页面上引用

<%= javascript_include_tag "lang/cn.js" %>

就可以了

Demo:
查看Demo