一个多月前去的涞滩古镇, 到今天才传上了照片.
涞滩古镇的城门 继续阅读
前天晚上和网友聊天时得知今天下午一个剧院里有越友演出,今天开了闹钟.起床时11点. 起床后连连打哈欠.
做饭, 吃饱后转着广场几个公车站找能到那个剧院的公车. 终于找到了, 可惜下错了站, 之后又上错上了另一辆公车, 最后才换了一个能到的. 到时已经2点多, 幸运的是原定1:30的演出刚好拖到此时要开幕.
场不算大, 但坐得算很满. 有一好心的大伯看我找座, 忙把我让到他身边的一个空位.
剧场上拉是一横幅, 从这字幅看这是为纪念越剧百年, 贵阳, 重庆, 成都三地的越友共同自费组织的一场表演.
开幕了, 上来两位很标准的主持念"经典"的台词
表演进行了大概三小时. 都是越剧选段, 选的最多的是梁祝. 表演者大多挂着XX剧团的名字, 最多的是一重庆的剧团. 表演者的水平就我个人听来都不怎么样. 给我印象最深的倒是其中唯一一对没有挂名的外地"越友"的演唱. 唱者声音洪亮, 字正腔圆, 韵味十足.他们演唱结束后掌声雷动, 赞声连连. 但最受观众欢迎的好像不是这一对, 而是一位来自本地的早期专业越剧演员. 听说以前她在重庆是红到发紫. 她上去清唱了一段. 除了不断的拉长音虚词, 我没听明白一个字. 但她下台后台下几乎沸腾了. 不少观众叫着"再来一个, 再来一个." 结果我担心的事件没有发生 –她说自己没有准备, 没有再来一个. 她让我明白了一个道理: 做网站不要看网站站长的背景功底, 而要看他做出来的网站; 或很多人技术不错, 但就不用来做正事, 都用到歪道上, 做出来的网站不一定有用. 正如越剧不是把词拉得越长越好听, 但功力好的演员却常常要为了表现自己功力而扫观众的兴.
这些演员将反复上台演出
这两位应该就是我说的唱得很不错的越友
再来一张, 可惜还是没照清楚
这个是从 碧玉簪 里选的." 婆婆"表情还是比较非富的.
可怜的祥林嫂
正如刚才说的,观众来了不少. 但基本上全是中老年, 其中又以女性居多. 或我, 一个二十多岁的男青年坐在剧场很显眼, 两个拿DV记录的都跟到我这边留个录像.
基本上全是中老年观众
这事让我很担心.
为什么看越剧的都是中老年呢? 这对越剧有什么影响呢?
究其原因有两种可能:
第一种可能是越剧本来就是为老年人开发的艺术. 从100年前, 到100年后的现在, 越剧就一直只是中老年人喜爱的. 人非要过40岁才有可能恋上越剧.
如果真是这样,应该也算是一件好事啊. 中国的老龄化问题听说很严重啊, 以后的老人会越来越多. 这样的话越剧的潜在观众也会更多.
第二可能是越剧本来是全民文化, 但后来受到电影,电视, 现代流行音乐, 电子游戏等其它娱乐项目的竞争,在现代社会中对新生代几乎没有了任何吸引力. 新青年都对越剧不感兴趣, 没有或很少新越剧迷加入, 从而越剧只被为固执的老资格戏迷所喜爱, 而这些人逝老, 形成只有中老越剧迷这种青黄不接的情景.
如果是这个情形的话越剧是把房子盖在沙堆上, 很危险啊.
无论上面是那个情况, 如果越剧能让青年喜欢, 都是好事. 为什么越剧不能吸引青年呢?
我上面提到过电影, 电视, 音乐, 游戏等的竞争, 如果这些东西都当作敌人, 而且他们的攻击力很强, 越剧现居弱势, 长此下去, 必将不敌啊.
所在我感觉越剧要兴, 必仗一字 — 变!
越剧很美, 但美中有不足, 有不让人喜欢的原因.
慢
就比如拉长音, 虽然运用得当, 很是可以强烈地加强人物情感. 但也是越剧在当今的一大把柄. 随着商品经济的发展, 人们进了快节奏的生活方式, 但戏剧太"慢"了. 一部戏近3个小时, 可实际上没说上几句话.假如唱一句要半分钟,年青观众没这个耐性子. 年青人说:"我一分钟几百万上下, 还听你这样磨嘴皮?"
(娘子——————————啊…(开唱), 没等开唱, 那"子—"就能吓跑一半的青年人, 你说这个"子—"除了吓人, 还有什么功能作用的???)
(五女拜寿 做得很好.)
俗
剧本少,剧本改来改去, 没什么新鲜情节. 剧情俗, 本来故事就不多, 而且还都很不合时代, 故事大多是给非常传统的人写的.
越剧没有电影那样的惊心场面, 没有游戏里面的激情互动. 但这两个不算缺点. 本来越剧就是通过朴素的背景服装唱词唱法来叙述看来平淡, 听完却感天动地之情的艺术. 有特色才有存在的价值.
我一直希望越剧能重兴, 但我说的重兴是怎样一个度呢?
从舞台表演到屏幕表演的改革(媒体传播向网络化发展, 舞台表演本身就限制越剧的传播)
屏幕后不再重唱梁祝(因为有录相了), 每年像贺岁片一样, 一年一部新片. 新故事, 新创意, (新演员).
人百年或已德高望重, 越剧百年或已将长存之道蕴含在自身的历史之中.
看完演出, 走出大门, 我径直又上了一辆公车. 到了终点站才发现又坐错了. 这才等来一辆能到沙坪坝的公车. 这车也不对–它竟开了一个多小时才到沙坪坝. 我把渴的眼睛发绿.
今天在想成功的条件, 现在总结有这几条:
成功在这里指完成一件事.
1.坚定决心
一要很想完成这事,欲望很强; 二要对这事坚贞不逾, 事不成不罢休, 包括在遇到多大的困难和挫折时都不改志向.
2.人际关系
好人际关系可以得到很多的帮助, 使事件的发展势势如破竹.
3.人力物力
做事的基础. 包括自己的技能(人力之一).
4.计谋策略
做事的方法
5.天时地利
如何才能长生不老是我一直在研究的课题之一.
虽然我还未能找到长生的方法.但我找到了一个很重要的线索.
要做到长生不老,起码要做到的一个就是:
不狂喜,不痛悲
情感是使人衰老,特别是悲愁. 我亲眼看到过N个中年人因为一件愁心的事半年之后成为老年人. 由中年过度到老年更决定的因素不是年月,而是情感.
古书更有一夜白发的事件无数, 我相信这是真实的.
要做到长寿,很重要的就是做到不狂喜,不痛悲.对得失都看得很淡泊.
要如何能做到这点呢?
本身的思想眼光应该是广博的. 心怀宇宙. 对于百,一为少,对于万,百为小,对于亿,万亦不足道. 对于年,日为短,于宇宙的长存,人之一生演的不过是百年的喜悲; 人活于浩瀚之天地,人的手脚舞动不过在尺寸之内. 之于无际的宇宙,人只是不起眼的一个小点, 算得了什么? 这样的一生得到什么,又失去什么, 一定要让人狂喜,一定要让人痛悲???
每在不顺心时我都会仰望天空, 看着广阔的天空或浩瀚的星空,我的不顺心有如宇宙间的一颗尘埃,微–不足道!
三种方式 Page Caching, Action Caching和 Fragment Caching
缓存默认只在production 环境下启动
Page Caching
caches_page :public_content
以URL为准
expire_page :action =>"public_content"
Action Caching
caches_action :premium_content
以URL为准
expire_action :action => "premium_content", :id => article
Page Caching 和 Action Caching的实例:
class ContentController < ApplicationController
before_filter :verify_premium_user, :except => :public_content
caches_page :public_content
caches_action :premium_content
cache_sweeper :article_sweeper,
:only => [ :create_article,
:update_article,
:delete_article ]
def public_content
@articles = Article.list_public
end
def premium_content
@articles = Article.list_premium
end
private
def verify_premium_user
return
user = session[:user_id]
user = User.find(user)
if user
unless user && user.active?
redirect_to :controller => "login", :action => "signup_new"
end
end
end
删除过期缓存内容:
app/models中加article_sweeper.rb
class ArticleSweeper < ActionController::Caching::Sweeper
observe Article
def after_create(article)
expire_public_page
end
def after_update(article)
expire_article_page(article.id)
end
def after_destroy(article)
expire_public_page
expire_article_page(article.id)
end
private
def expire_public_page
expire_page(:controller => "content", :action => ‘public_content’)
end
def expire_article_page(article_id)
expire_action(:controller => "content",
:action => "premium_content",
:id => article_id)
end
end
app/public/content/show/1默认caches_page文件路径
app/public/content/show/1.html
Fragment Caching
controller:
class Blog1Controller < ApplicationController
def list
@dynamic_content = Time.now.to_s
unless read_fragment(:action => ‘list’)
logger.info("Creating fragment")
@articles = Article.find_recent
end
end
end
#read_fragment()查看一个action的fragment缓存是否存在
view:
<%= @dynamic_content %> <!– 动态内容 –>
<% cache do %> <!– 缓存开始–>
<ul>
<% for article in @articles -%>
<li><p><%= h(article.body) %></p></li>
<% end -%>
</ul>
<% end %> <!– 结束缓存 –>
<%= @dynamic_content %> <!– 其它动态内容 –>
使用多个缓存段:
<% cache(:action => ‘list’, :part => ‘articles’) do %>
<ul>
<% for article in @articles -%>
<li><p><%= h(article.body) %></p></li>
<% end -%>
</ul>
<% end %>
<% cache(:action => ‘list’, :part => ‘counts’) do %>
<p>There are a total of <%= @article_count %> articles.</p>
<% end %>
#使用:part参数区分同一action下的不同缓存段
缓存过期
controller:
class Blog2Controller < ApplicationController
def list
@dynamic_content = Time.now.to_s
@articles = Article.find_recent
@article_count = @articles.size
end
def edit
# 编辑文章时不更新统计缓存
expire_fragment(:action => ‘list’, :part => ‘articles’)
redirect_to(:action => ‘list’)
end
def delete
#删除文章时同时删除两个缓存
expire_fragment(:action => ‘list’, :part => ‘articles’)
expire_fragment(:action => ‘list’, :part => ‘counts’)
redirect_to(:action => ‘list’)
end
end
expire_fragment()可接正则表达式
expire_fragment(%r{/blog2/list. })
Fragment Caching存储选项设置:
ActionController::Base.fragment_cache_store = <下面的选项之一>
ActionController::Caching::Fragments::FileStore.new(path)
ActionController::Caching::Fragments::DRbStore.new(url)
ActionController::Caching::Fragments::MemCachedStore.new(host)
自动增加预载model方法:
class StoreController < ApplicationController
model :cart, :line_item
observer :stock_control_observer
# …
如果没有找到相应的action, method_missing()将被调用
如果没有任何action, Rails会直接找template显示.
Ruby on Rails链接
Routing Requests
配置文件:config/routes.rb
ActionController::Routing::Routes.draw do |map|
map.connect ‘:controller/service.wsdl’, :action => ‘wsdl’
map.connect ‘:controller/:action/:id’
end
map.connect可用参数:
:defaults => { :name => "value", …}
设默认值,默认为:defaults => { :action => "index", :id => nil }
:requirements => { :name =>/regexp/, …}
:name => value
:name => /regexp/
实例:
ActionController::Routing::Routes.draw do |map|
#从上到下优先级降低.
#’http://my.app/blog/' 直接显示 index
map.connect "blog/",
:controller => "blog",
:action =>"index"
#按日期访问博客文章列表
map.connect "blog/:year/:month/:day",
:controller =>"blog",
:action =>"show_date",
:requirements => { :year => /(19|20)\d\d/,
:month => /[01]?\d/,
:day => /[0-3]?\d/},
:day =>nil,
:month =>nil
# 按文章ID显示文章内容
map.connect "blog/show/:id",
:controller => "blog",
:action =>"show",
:id => /\d+/
# 管理页面,常规
map.connect "blog/:controller/:action/:id"
# 其它
map.connect "*anything",
:controller =>"blog",
:action =>"unknown_request"
#=> URL>junk
#=>@params = {:anything=>["junk"], :controller=>"blog", :action=>"unknown_request"}
end
链接生成url_for
@link = url_for :controller => "store", :action => "display", :id => 123
生成:http://pragprog.com/store/display/123
url_for(:controller => "store", :action => "list",
:id => 123, :extra => "wibble")
生成:http://rubygarden.org/store/list/123?extra=wibble
url_for(:overwrite_params => {:year => "2002"})
生成:http://pragprog.com/blog/2002/4/15
#url_for会使用默认环境中的参数自动补充出完整的地址
#但一般补最后面的
#使用:overwrite_params使之补前面的.
url_for(:year=>year, :month=>sprintf("%02d", month), :day=>sprintf("%02d", day))
用来填充位数???
url_for(:controller => "/store", :action => "purchase", :id => 123)
#=> http://my.app/store/purchase/123
url_for(:controller => "/archive/book", :action => "record", :id => 123)
#=> http://my.app/archive/book/record/123
redirect_to(:action =>’delete’, :id => user.id)
# 和上面的一样:
redirect_to(:action => ‘delete’, :id => user)
default_url_options()
:anchor string #+string
:host string (helper.pragprog.com:8080)
:only_path boolean
:protocol string ("https://";)
:trailing_slash boolean (+"/"?)
有名字的 Routes
map.date "blog/:year/:month/:day",
:controller =>"blog",
:action =>"show_date",
:requirements => { :year => /(19|20)\d\d/,
:month => /[01]?\d/,
:day => /[0-3]?\d/},
:day =>nil,
:month =>nil
可调用
date_url(:year => 2003, :month => 2)
#=> http://pragprog.com/blog/2003/2
方法
把action藏起来,让它使用URL访问不了.
hide_action :check_credit
def check_credit(order)
# …
end
Controller Environment
request
domain()
remote_ip()
env() 如:request.env['HTTP_ACCEPT_LANGUAGE']
method (:delete, :get, :head,:post, or :put.)
delete?, get?, head?, post?, and put?
class BlogController < ApplicationController
def add_user
if request.get?
@user = User.new
else
@user = User.new(params[:user])
@user.created_from_ip = request.env["REMOTE_HOST"]
if @user.save
redirect_to_index("User #{@user.name} created")
end
end
end
end
params
cookies
response
session
headers
runder()
更改默认template目录
ActionController::Base.template_root=dir_path
render(:text=>string)
class HappyController < ApplicationController
def index
render(:text =>"Hello there!")
end
end
render(:inline=>string, [ :type =>"rhtml"|"rxml"] )
class SomeController < ApplicationController
if RAILS_ENV == "development"
def method_missing(name, *args)
render(:inline => %{
<h2>Unknown action:#{name}</h2>
Here are the request parameters:<br/>
<%= debug(params) %> })
end
end
end
render(:action =>action_name)
def display_cart
if @cart.empty?
render(:action => :index)
else
# …
end
end
render(:file =>path, [ :use_full_path =>true|false] )
render(:template =>name)
class BlogController < ApplicationController
def index
render(:template =>"blog/short_list")
end
end
render(:partial =>name, …)
render(:nothing => true)
render_to_string() 不发送,直接转为string
发送
send_data
def sales_graph
png_data = Sales.plot_for(Date.today.month)
send_data(png_data, :type => "image/png", :disposition => "inline")
end
send_file
def send_secret_file
send_file("/files/secret_list")
headers["Content-Description"] = "Top secret"
end
有些地方使用redirect_to代替render
redirect_to(:action => ‘display’)
redirect_to(options…)
redirect_to(path)
redirect_to(url)
Cookies and Sessions
Cookies只能存String
class CookiesController < ApplicationController
def action_one
cookies[:the_time] = Time.now.to_s
redirect_to :action =>"action_two"
end
def action_two
cookie_value = cookies[:the_time]
render(:text => "The cookie says it is #{cookie_value}")
end
end
cookies[:marsupial] = { :value => "wombat",
:expires => 30.days.from_now,
:path =>"/store" }
可用选项 :domain, :expires,:path, :secure, and :value
Sessions
保存model时要先预载:
class BlogController < ApplicationController
model :user_preferences
设置session:
ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS[:session_key] = ‘my_app’
可用选项:
:database_manager
:session_domain
:session_id
:session_key
:session_path
:session_secure
Session保存选择:
:database_manager => CGI::Session::PStore
flat file (单服务器推荐)
:database_manager => CGI::Session::ActiveRecordStore
:database_manager => CGI::Session::DRbStore
:database_manager => CGI::Session::MemCacheStore
Flash用于在两个action传输暂时信息
flash.now用法实例:
class BlogController
def display
unless flash[:note]
flash.now[:note] = "Welcome to my blog"
end
@article = Article.find(params[:id])
end
end
flash.keep用法实例:
class SillyController
def one
flash[:note] = "Hello"
redirect_to :action => "two"
end
def two
flash.keep(:note)
redirect_to :action => "three"
end
def three
# flash[:note] => "Hello"
render
end
end
Filters
class BlogController < ApplicationController
before_filter :authorize, :only => [ :delete, :edit_comment ]
after_filter :log_access, :except => :rss
# …
before_filter可用来替换全局页面中的字符,如{$title}
也可用来给页面 Zlib压缩
Around Filters可用来计算action用时
Verification
class BlogController < ApplicationController
verify :only => :post_comment,
:session => :user_id,
:add_flash => { :note =>"You must log in to comment"},
:redirect_to => :index
# …
使用范围:
:only =>:name or [ :name, ... ]
:except =>:name or [ :name, ... ]
通过条件:
:flash =>:key or [ :key,... ]
:method =>:symbol or [ :symbol, ... ](:get, :post, :head, or :delete)
:params =>:key or [ :key,... ]
:session =>:key or [ :key,... ]
反应:
:add_flash =>hash
:redirect_to =>params
GET Requests
GET用来获取信息
POST用来传输更改数据库的信息
<%= link_to ‘删除评论’, { :action => ‘com_destroy’, :id => comment },
:confirm =>"你确定要删除这则评论吗?",
:post => true %>
使用forms和buttons
Callbacks
class User < ActiveRecord::Base
before_destroy :dont_destroy_dave
def dont_destroy_dave
raise "Can’t destroy dave" if name == ‘dave’
end
end
class Order < ActiveRecord::Base
# ..
def before_save
self.payment_due ||= Time.now + 30.days
end
end
class Order < ActiveRecord::Base
before_validation :normalize_credit_card_number
after_create do |order|
logger.info "Order #{order.id} created"
end
protected
def normalize_credit_card_number
self.cc_number.gsub!(/-\w/, ”)
end
end
Callback Objects 全局可以访问
class CreditCardCallbacks
# Normalize the credit card number
def before_validation(model)
model.cc_number.gsub!(/-\w/,”)
end
end
class Order < ActiveRecord::Base
before_validation CreditCardCallbacks.new
# …
end
Subscription < ActiveRecord::Base
class
before_validation CreditCardCallbacks.new
# …
end
可用于数据加密
格式化数据类型:
class LineItem < ActiveRecord::Base
def total_price
Float(read_attribute("total_price"))
end
end
数量单位转换:
class ProductData < ActiveRecord::Base
CUBITS_TO_INCHES = 18
def length
read_attribute("length") * CUBITS_TO_INCHES
end
def length=(inches)
write_attribute("length", Float(inches) / CUBITS_TO_INCHES)
end
end
find_by_sql没有读取PK时不能保存的实例:
result = LineItem.find_by_sql("select quantity from line_items")
result.each do |li|
li.quantity += 2
li.save
end
有特殊功能的段名
created_at, created_on, updated_at, updated_on
ror自动更新的时间段
修改ActiveRecord::Base.default_timezone = :utc参数更改变时区
lock_version
type
(employee, manager, person..)
id
XXX_id (FK)
xxx_count
position (acts_as_list)
partent_id (acts_as_tree)
可以自定义validate(), 这个方法在每次保存数据时都会被调用.
如:
def validate
if name.blank? && email.blank?
errors.add_to_base("You must specify a name or an email address")
end
end
同时也可以自定义 validate_on_create(), validate_on_update()方法.
valid?()方法可以随时调用,用来测试数据是否能通过校验
返回的错误信息可用 error_messages_for(model)方法显示.
如:<%= error_messages_for ‘article’ %>
校验大全:
validates_acceptance_of
指定checkbox应该选中. (如:(*)我同意条款)
用法:validates_acceptance_of attr… [ options... ]
参数:message text 默认:“must be accepted.”
:on :save, :create, or :update
实例:
class Order < ActiveRecord::Base
validates_acceptance_of :terms,
:message => "Please accept the terms to proceed"
end
validates_associated
查验指定的object.
用法:validates_associated name… [ options... ]
参数:message text 默认: is “is invalid.”
:on :save, :create, or :update
实例:
class Order < ActiveRecord::Base
has_many :line_items
belongs_to :user
validates_associated :line_items,
:message => "are messed up"
validates_associated :user
end
validates_confirmation_of
数据重校
用法:validates_confirmation_of attr… [ options... ]
参数:message text 默认 “doesn’t match confirmation.”
:on :save, :create, or :update
实例:
对密码表:
<%= password_field "user", "password" %><br />
<%= password_field "user", "password_confirmation" %><br />
#第二表名为xxxx_confirmation
class User < ActiveRecord::Base
validates_confirmation_of :password
end
validates_each
使用block检验一个或一个以上参数.
用法:validates_each attr… [ options... ] { |model, attr, value| … }
参数:allow_nil boolean 设为true时跳过nil对象.
:on :save, :create, or :update
实例:
class User < ActiveRecord::Base
validates_each :name, :email do |model, attr, value|
if value =~ /groucho|harpo|chico/i
model.errors.add(attr,"You can’t be serious, #{value}")
end
end
end
validates_exclusion_of
确定被检对象不包括指定数据
用法:validates_exclusion_of attr…, :in => enum [ options... ]
#enum指一切可用include?()判断的范围.
参数:allow_nil 设为true将直接跳过nil对象.
:in (or :within) enumerable
:message text 默认为: “is not included in the list.”
:on :save, :create, or :update
实例:
class User < ActiveRecord::Base
validates_exclusion_of :genre,
:in => %w{ polka twostep foxtrot },
:message =>"no wild music allowed"
validates_exclusion_of :age,
:in => 13..19,
:message =>"cannot be a teenager"
end
validates_inclusion_of
确认对象包括在指定范围
用法:validates_inclusion_of attr…, :in => enum [ options... ]
参数:allow_nil 设为true直接跳过nil对象
:in (or :within) enumerable An enumerable object.
:message text 默认:“is not included in the list.”
:on :save, :create, or :update
实例:
class User < ActiveRecord::Base
validates_inclusion_of :gender,
:in => %w{ male female },
:message =>"should be ‘male’ or ‘female’"
validates_inclusion_of :age,
:in => 0..130,
:message =>"should be between 0 and 130"
end
validates_format_of
用正则检验对象
用法:validates_format_of attr…, :with => regexp [ options... ]
参数:message text 默认为: “is invalid.”
:on :save, :create, or :update
:with 正则表达式
实例:
class User < ActiveRecord::Base
validates_format_of :length, :with => /^\d+(in|cm)/
end
validates_length_of
检查对象长度
用法:validates_length_of attr…, [ options... ]
参数:in (or :within) range
:is integer
:minimum integer
:maximum integer
:message text 默认文字会根据参数变动,可使用%d 取代确定的最大,最小或指定数据.
:on :save, :create, or :update
:too_long text 当使用了 :maximum后的 :message
:too_short text ( :minimum )
:wrong_length ( :is)
实例:
class User < ActiveRecord::Base
validates_length_of :name, :maximum => 50
validates_length_of :password, :in => 6..20
validates_length_of :address, :minimum => 10,
:message =>"seems too short"
end
validates_numericality_of
检验对象是否为数值
用法:validates_numericality_of attr… [ options... ]
参数:message text 默认 “is not a number.”
:on :save, :create, or :update
:only_integer
实例:
class User < ActiveRecord::Base
validates_numericality_of :height_in_meters
validates_numericality_of :age, :only_integer => true
end
validates_presence_of
检验对象是否为空
用法:validates_presence_of attr… [ options... ]
参数:message text 默认:“can’t be empty.”
:on :save, :create, or :update
实例:
class User < ActiveRecord::Base
validates_presence_of :name, :address
end
validates_uniqueness_of
检验对象是否不重复
用法:validates_uniqueness_of attr… [ options... ]
参数:message text 默认: “has already been taken.”
:on :save, :create, or :update
:scope attr 指定范围
实例:
class User < ActiveRecord::Base
validates_uniqueness_of :name
end
class User < ActiveRecord::Base
validates_uniqueness_of :name, :scope =>"group_id"
end
#指定在同一group_id的条件下不重复.
常用正则:
E-Mail地址格式:
validates_format_of :email,
:with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i,
:message => ‘email must be valid’
网址格式:
validates_uri_existence_of :url, :with =>
/(^$)|(^(http|https)://[a-z0-9] ([-.]{1}[a-z0-9] )*.[a-z]{2,5}(([0-9]{1,5})?/.*)?$)/ix
Acts As List实例:
在子表中加parent_id和position
定义:
class Parent < ActiveRecord::Base
has_many :children, :order => :position
end
class
Child < ActiveRecord::Base
belongs_to :parent
acts_as_list :scope => :parent_id
#:scope 指定在parent_id相同范围内.
end
向表中添加数据:
parent = Parent.new
%w{ One Two Three Four}.each do |name|
parent.children.create(:name => name)
end
parent.save
定义显示方法:
def display_children(parent)
puts parent.children.map {|child| child.name }.join(", ")
end
调用实例:
display_children(parent) #=> One, Two, Three, Four
puts parent.children[0].first? #=> true
#使用last?(), first?()判断行位置
two = parent.children[1]
puts two.lower_item.name #=> Three
puts two.higher_item.name #=> One
#使用.lower_item访问下一行数据, 使用.higher_item访问上一行数据,使用
parent.children[0].move_lower
parent.reload
display_children(parent) #=> Two, One, Three, Four
#使用mover_lower(), mover_higher()可移动行数据
#使用parent.reload刷新数据
parent.children[2].move_to_top
parent.reload
display_children(parent) #=> Three, Two, One, Four
#使用move_to_top(), move_to_bottom()移动行数据
parent.children[2].destroy
parent.reload
display_children(parent) #=> Three, Two, Four
#一行数据删除后其下面的行会自动跟上
Acts As Tree实例:
向子表新增parent_id (int), 并将设定为表内关联键
定义方法:
class Category < ActiveRecord::Base
acts_as_tree :order =>"name"
end
向表格添加数据:
root = Category.create(:name => "Books")
fiction = root.children.create(:name =>"Fiction")
non_fiction = root.children.create(:name => "Non Fiction")
non_fiction.children.create(:name =>"Computers")
non_fiction.children.create(:name =>"Science")
non_fiction.children.create(:name =>"Art History")
fiction.children.create(:name =>"Mystery")
fiction.children.create(:name => "Romance")
fiction.children.create(:name =>"Science Fiction")
定义显示方法:
def display_children(parent)
puts parent.children.map {|child| child.name }.join(", ")
end
调用实例:
display_children(root) # Fiction, Non Fiction
sub_category = root.children.first
puts sub_category.children.size #=> 3
display_children(sub_category) #=> Mystery, Romance, Science Fiction
non_fiction = root.children.find(:first, :conditions => "name = ‘Non Fiction’")
display_children(non_fiction) #=> Art History, Computers, Science
puts non_fiction.parent.name #=> Books
:counter_cache => true+children_count段也可以在这里使用.用来自动计算子表行数.