Active Record objects don‘t specify their attributes directly, but rather infer them from the table definition with which they‘re linked. Adding, removing, and changing attributes and their type is done directly in the database. Any change is instantly reflected in the Active Record objects. The mapping that binds a given Active Record class to a certain database table will happen automatically in most common cases, but can be overwritten for the uncommon ones.
本章就来学习一下ROR的特色的ActiveRecord
用下面语句创建一个model名字叫event,具有name,description,is_public,capacity属性。
script/generate model event name:string description:text is_public:boolean capacity:integer
接下来创建表
rake db:migrate
查看一下DB中是否成功创建event表
接下来用一组命令语句来展示一下(script/console):
>> event = Event.new event = Event.new => #<Event id: nil, name: nil, description: nil, is_public: nil, capacity: nil, created_at: nil, updated_at: nil> >> event.name = "Ruby course" event.name = "Ruby course" => "Ruby course" >> event.description = "fooobarrrrr" event.description = "fooobarrrrr" => "fooobarrrrr" >> event.save event.save => true >> event.id event.id => 1 >> e = Event.find(1) e = Event.find(1) => #<Event id: 1, name: "Ruby course", description: "fooobarrrrr", is_public: nil, capacity: nil, created_at: "2010-08-11 07:42:15", updated_at: "2010-08-11 07:42:15"> >> e = Event.find_by_name("Ruby course") e = Event.find_by_name("Ruby course") => #<Event id: 1, name: "Ruby course", description: "fooobarrrrr", is_public: nil, capacity: nil, created_at: "2010-08-11 07:42:15", updated_at: "2010-08-11 07:42:15"> >> e = Event.find(:first, :conditions => { :name => "Ruby course" }) e = Event.find(:first, :conditions => { :name => "Ruby course" }) => #<Event id: 1, name: "Ruby course", description: "fooobarrrrr", is_public: nil, capacity: nil, created_at: "2010-08-11 07:42:15", updated_at: "2010-08-11 07:42:15"> >> e = Event.find(:first, :conditions => ["name = ?", "Ruby course"]) e = Event.find(:first, :conditions => ["name = ?", "Ruby course"]) => #<Event id: 1, name: "Ruby course", description: "fooobarrrrr", is_public: nil, capacity: nil, created_at: "2010-08-11 07:42:15", updated_at: "2010-08-11 07:42:15"> >> e.name e.name => "Ruby course" >> e.update_attributes( :name => 'abc', :is_public => false ) e.update_attributes( :name => 'abc', :is_public => false ) => true >> e.destroy e.destroy => #<Event id: 1, name: "abc", description: "fooobarrrrr", is_public: false, capacity: nil, created_at: "2010-08-11 07:42:15", updated_at: "2010-08-11 07:43:01"> >> Event.find(:all, :limit => 2, :order => 'id DESC') Event.find(:all, :limit => 2, :order => 'id DESC') => [] >>
注意观察过程,及语法特点。
model的基本应用学会之后,我们来学一下Model Validation
编辑:/app/models/event.rb
class Event < ActiveRecord::Base validates_presence_of :name end
离开 console 重新进入,或者执行 reload!
>> event = Event.new event = Event.new => #<Event id: nil, name: nil, description: nil, is_public: nil, capacity: nil, created_at: nil, updated_at: nil> >> event.save event.save => false >> event.errors.full_messages event.errors.full_messages => ["Name can't be blank"] >> event.name = 'ihower' event.name = 'ihower' => "ihower" >> event.save event.save => true >>
看来,我们刚才追加的Validation已经生效了。
接下来不适用脚手架来创建一套CRUD应用。
script/generate controller events
编辑文件:app/controllers/events_controller.rb
def index @events = Event.find(:all) end def show @event = Event.find(params[:id]) end def new @event = Event.new end def create @event = Event.new(params[:event]) @event.save redirect_to :action => :index end def edit @event = Event.find(params[:id]) end def update @event = Event.find(params[:id]) @event.update_attributes(params[:event]) redirect_to :action => :show, :id => @event end def destroy @event = Event.find(params[:id]) @event.destroy redirect_to :action => :index end
新增:/app/views/events/index.html.erb
<ul> <% @events.each do |event| %> <li> <%= link_to event.name, :controller => 'events', :action => 'show', :id => event %> <%= link_to 'edit', :controller => 'events', :action => 'edit', :id => event %> <%= link_to 'delete', :controller => 'events', :action => 'destroy', :id => event %> </li> <% end -%> </ul> <%= link_to 'new event', :controller => 'events', :action => 'new' %>
新增:/app/views/events/show.html.erb
<%=h @event.name %> <%=h @event.description %> <p> <%= link_to 'back to index', :controller => 'events', :action => 'index' %> </p>
新增:/app/views/events/new.html.erb
<% form_for @event, :url => { :controller => 'events', :action => 'create' } do |f| %> <%= f.label :name, "Name" %> <%= f.text_field :name %> <%= f.label :description, "Description" %> <%= f.text_area :description %> <%= f.submit "Create" %> <% end %>
新建:/app/views/events/edit.html.erb
<% form_for @event, :url => { :controller => 'events', :action => 'update', :id => @event } do |f| %> <%= f.label :name, "Name" %> <%= f.text_field :name %> <%= f.label :description, "Description" %> <%= f.text_area :description %> <%= f.submit "Update" %> <% end %>
访问网址:http://localhost:3000/events
看看是不是已经看到没有任何样式的画面了。
画面样式如何加呢?每个画面引入?太老土了。看看ROR的做法:
新建:/app/views/layout/application.html.erb
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="content-type" content="text/html;charset=UTF-8" /> <title>Posts: <%= controller.action_name %></title> <%= stylesheet_link_tag 'scaffold' %> </head> <body style="background: #EEEEEE;"> <p style="color: green"><%= flash[:notice] %></p> <%= yield %> </body> </html>
在刷新一下画面,呵呵~是不是变成灰色背景了?这说明已经剩下了。
如果你还有其他的controller可以看看是不是都变色了。
这个是全局设置。如果想知识应用到events怎么做呢?
很简单,创建的文件名application.html.erb->events.html.erb
再看看,是不是只有events下的文件生效了呢。
很方便吧。
接下来看看flash
然后用画面跑一边所有应用,是不是对应的成功消息都打印出来了。
下面来看看部分模板(Partial template)的使用方法:
将 new.html.erb 和 edit.html.erb 的窗体程序移往 _form.html.erb,内容如下
<%= f.label :name, "Name" %> <%= f.text_field :name %> <%= f.label :description, "Description" %> <%= f.text_area :description %>
在 new.html.erb 和 edit.html.erb 的窗体内加回
<%= render :partial => 'form', :locals => { :f => f } %>
再跑一圈画面,应该还是跟之前一样的,说明编辑和创建画面已经成功的应用了模板文件了。
再来看看before_filter
在 events_controller.rb 中加入:
before_filter :find_event, :only => [ :show, :edit, :update, :destroy]
创建下面方法:
protected def find_event @event = Event.find(params[:id]) end
删除 show, edit, update, destroy 方法中的 @event = Event.find(params[:id])
这样就达到了在执行show, edit, update, destroy等几个方法前都共同调用了find_event方法,并把值保存在实例变量中。
下面接续学习Model validation
编辑 /app/models/event.rb 加入
validates_presence_of :name
修改/app/controllers/events.rb 的 create 和 update 方法
def create @event = Event.new(params[:event]) if @event.save flash[:notice] = "创建成功" redirect_to :action => :index else render :action => :new end end def update if @event.update_attributes(params[:event]) flash[:notice] = "修改成功" redirect_to :action => :show, :id => @event else render :action => :edit end end
编辑 new.html.erb 及 edit.html.erb 加入
<%= error_messages_for :event %>
回到画面上,在编辑画面或者新建画面中不输入名字,然后点保存,会看到下面的样子:
说明生效了。
常用的功能还有分页,让我们组装一下:
script/plugin install git://github.com/mislav/will_paginate
windows下默认没有安装git,到这里下载:http://code.google.com/p/msysgit/downloads/list
然后就可以使用上面的语句安装了。
安装完之后,修改 /app/controllers/events_controller.rb 的 index 方法如下:
def index @events = Event.paginate(:page => params[:page], :per_page => 3) end
編輯 /app/views/events/index.html.erb,循环外加入
<%= will_paginate @events %>
添加超过3天数据看看,是不是出现翻页了。