啟動項目:
ruby script/server -e development(默認)
ruby script/server -e test
ruby script/server -e production
在編寫ruby代碼時,如果要引用另一個文件中的類和模塊,需要使用require關鍵字,但是當我們在rails中引用另一個文件中的類和模塊時,rails會自動把類名稱根據命名約定改為文件名,然后在同一目錄下加載該文件。
按模塊組織控制器:
ruby script/generate controller Admin::Book action1 action2
admin模塊下的book_controller控制器
Rails給Enumerable類擴展的方法
1》 group_by: 將一個對象集合分組,針對每個對象調用塊,然后根據代碼塊的返回值作為分組的鍵,值是所有擁有同一個鍵的對象組成的數組。
eg:
User.all.group_by{|user| user.sex}
User.all.group_by(&:name)
2》 sum: 對集合進行加總,把每個元素傳遞給一個代碼塊,并對代碼塊返回的值進行累加。
User.all.sum(&:id) 返回所有user對象的id的和
3》 in_groups_of(arg1, arg2)? 將某一個數組分為子元素由arg1個元素組合的數組元素組成的數組,出現無法填充的值由arg2填補。
eg:
[1,2,3,4,5].in_groups_of(2,"blank")???? =>?????
[[1,2],[3,4],[5,"blank"]]
字符串擴展
str[0] 第一個字符的Ascill碼。
str[2..3] 返回字符串的第三個字符開始的3個字符組成的字符串。
str.at(0) 第一個字符
str.to(4) 前5個字符組成的字符串
str.from(4) 最后5個字符組成的字符串
str.first
str.last
str.starts_with?(字符串)
str.ends_with?(字符串)
str.each_char{|char| char.upcase}
str.pluralize 復數形式
str.singularize? 單數形式
str.humanize
str.titleize
對數值的擴展:
figure.ordinalize?? 返回數字的序數形式
figure.bytes、kilobytes、megabytes、gigabytes、terabytes、
perabytes、exabyte? 數據大小
figure.seconds、minutes、hours、days、weeks、fortnights、months、years? 時間
注意:? ago、 until、 from_now、 since
eg:?
1.day.ago
1.day.ago(Time.now)
時間和日期的擴展
now = Time.now
now.to_s(:short)、to_s(:db)、to_s(:long)、to_s(:rfc822)
now.ago(2.days)、since(2.days)
change(:hour => 12)? 改變日期的hour為12
advance(:hour => 12)? 推遲日期的12hour
to_date、to_time
at_beginning_of_week、at_beginning_of_month、at_beginning_of_quarter(季)、at_beginning_of_year
ruby符號的擴展:
posts.group_by{|post| post.author_id}
posts.group_by(&:author_id)
with_options的使用:
Rails里有些方法使用一個Hash作為最后一個可選的參數,如果對多個方法有同樣的選項,我們可以使用with_options來減少冗余:
eg:
with_options :if => :should_validate_password? do |user|?
? user.validates_presence_of :password?
? user.validates_confirmation_for :password?
? user.validates_format_of :password, :with => /^[^\s]+$/
end
遷移任務:
create_table??
:force => true? 如果表存在,強制刪除,然后再創建表
:temporary => true? 創建一張臨時表,程序與數據庫斷開鏈接,則表被刪除。
:options => "xxxx"? 指定針對于底層數據庫的選項,這些選項會被加到create table語句的后面
:primary_key 主鍵
:id => false? 沒有主鍵的表
如果遷移任務 提供的方法 不夠滿足你 的需要,也 可以使用數 據庫專有的 功能:使用execute() 方法就可以運行原生 SQL 語句。例如:給表加上外鍵
class CreateLineItems < ActiveRecord::Migration
??? def self.up
????? create_table :line_items do |t|
??????? t.column :product_id, :integer
??????? t.column
rder_id,???? :integer
????? end
????? execute "alter table line_items
????????? add constraint fk_line_item_products
????????? foreign key (product_id) references products(id)"
??? end
???? def self.down
????? drop_table :line_items
???? end
end
ActiveRecord::Base
column_names? 屬性組成的數組
columns_hash["屬性名稱"]? 屬性名稱信息
屬性_before_type_cast? 讀取屬性時,ActiveRecod會盡量將得到的值轉型成適當的ruby類型,如果我們希望的到屬性的原始值,可以在屬性名稱后面加上before_type_cast。
eg:User.first.created_at??? =>?? 2010-06-24 09:41:17
連接數據庫:? ActiveRecord::Base.establish_connection(:adapter => "mysql", :host => "localhost", :database => "rails", :username => "root", :password => "1234")
防止惡意注入:
1> 問號占位符:?? User.find(:all, :conditions => ["id > ?", 3]
2> 命名占位符:?? User.find(:all, :conditions => ["id > :id", {:id => 3}])
注意:
命名占位符的語句可以轉換為
User.find(:all, :conditions => ["id > :id", params[:user]])
獲取字段統計信息:
average:?
maximum:
minimum:
sum? :
count? :
以上方法的參數:?
:conditions、:joins、:limit、:order、:having、:select、 :distinct
eg:
Order.maximum :amount, :group => "state", :limit => 3,
rder => "max(amount) desc"
擁有訂單最大的三個州
更新操作:
update_attribute、update_attributes、update、update_all
創建操作:
create、create!、save、save!
刪除數據:
delete、delete_all、destroy、destroy_all
delete繞過了ActiveRecord的回調和驗證,destory沒有繞過回調和驗證
序列化數據:
serialize :屬性
序列化的屬性可以直接存入Array和hash類型的數據,也可以直接讀出來使用
缺點:
ruby應用之外的應用訪問序列化的數據時,除非它能夠理解yaml格式,否則無法獲取這個字段的信息。
彌補這種缺點的方式是用對象聚合的方式來實現類似的效果
聚合/組合:
聚合可以把一個或多個屬性封裝為一個類,然后這個類里可以添加操作屬性的方法,這樣我們就可以實現序列化所要實現的目的了,而且可以避免序列化的缺點。
composed_of :attr_name, :class_name => 類名稱, :mapping => [字段與屬性組成的數組]
eg:
class Xingxi < ActiveRecord::Base
? composed_of :inf, :class_name => "Inf", :mapping => [[:name, :name], [:phone, :phone]]
end
class Inf
??? attr_reader :name, :phone
??? def initialize(name, phone)
??????? @name = name
??????? @phone = phone
??? end
??? def to_s
????? [@name, @phone].compact.join(" ")
??? end
end
inf = Inf.new("zcy",? "12344454")
Xingxi.create(:inf => inf)
注意:
教程上指出? :class_name對應的“類名稱”可以是類常量,也可以是包含類常量的字符串,但實際上只能是包含類常量的字符串,如果類名恰好是屬性名的混合大寫形式,那么class_name可以省略,但是實際上不可以,包括:mapping也不可以。
關聯:
class Line < ActiveRecord::Base
? belongs_to :product
end
belongs_to :product? 會產生以下方法
1>:product(force_reload=false) 返回關聯的product對象,默認情況下product對象會被緩存,當force_reload=true時,將重新查詢數據庫。
2>:product=: line對象和product對象關聯起來,將line記錄的外鍵值設為product的主鍵值,如果product沒有保存,line保存的時候會保存product,包括外鍵。
3>:build_product(attributes={}) 新建一個product對象,用指定的屬性對其初始化,相當于product=Product.new(attributes)。
4>:build_create(attributes={}) 創建一個product對象,與line關聯,保存product對象。
order:? has_one中也有order,主要用于例如最后一個***,此時便可以用order指定排序。
:dependent?? :destroy(true)、:nullify、 false
??? :destroy?? 刪除記錄的同時也刪除子記錄
??? :nullify?? 刪除記錄的同時刪除子記錄的外鍵
??? false????? 只刪除記錄
has_many :lines
class Product < ActiveRecord::Base
? has_many :lines
end
has_many :lines? 會產生以下方法
lines(force_reload=false)? 同上
lines.build(attributes = {})
lines.create(attributes = {})
lines << line? 將當前line對象添加到lines對象數組里
lines.push(line對象) line對象添加到lines
lines.delete(line,...) 刪除一個或多個line對象,如果關聯為:destroy => :destroy,子對象被刪除,否則只是刪除子對象的外鍵,打斷與父對象的關聯。
lines.delete_all? 調用所有子對象的delete方法
lines.destroy_all?? 調用所有子對象的destroy方法
lines.clear? 和delete一樣,不同的是clear針對的是所有的子對象。
lines.find(options)
lines.count(options)
lines.size
lines.length? 強制加載所有子對象,返回對象的集合。
lines.empty?
lines.replace(line對象數組)? line對象數組替換原先的lines
lines.sum(options) 不便利內存中的子對象集合,直接在數據庫端操作
lines.uniq? 返回一個數組,包含所有具備獨立id的子對象
1> finder_sql: 重新定義了統計子記錄的sql語句
?? counter_sql: 重新定義了統計子記錄的數目
注意: 如果指定了finder_sql而沒有指定counter_sql,finder_sql中的子句會被替換為select count(*),然后記錄子記錄的數量。
eg:
has_many
ingxis, :finder_sql => "select x.* from xingxis x, infos i where x.info_id = i.id and x.id > 4"
作用: 當:conditions無法滿足時,:finder_sql顯的非常重要。
:order : 以特定的順序排列
:conditions : 返回符合條件的子記錄
:dependent?? :destroy、:nullify、 false
??? :destroy?? 刪除記錄的同時也刪除子記錄
??? :nullify?? 刪除記錄的同時刪除子記錄的外鍵
??? false????? 只刪除記錄
多對多的關聯有兩種
1: 利用默認的關聯表
2:自己創建關聯表,利用關聯中的:through
:through?? 告訴rails通過guanlians表來導航關聯
:source? 用來指定關聯在那個屬性上
:uniq => true? 去掉重復的對象 等同于 :select => "distinct books.*"
eg:
class Kind < ActiveRecord::Base
??? has_many :guanlians
??? has_many :readers, :through => :guanlians, :source => :book
end
注意:
has_many :reader1s,:conditions => "guanlians.cishu > 0"
當使用conditions不能很好的表達時,無法提供參數,可以考慮以下格式,而且當同樣的方法被多次調用時,可以將方法寫在模塊中,然后在關聯中:extend => "模塊名稱" 來調用。
has_many :readers do
??? def reader(limit = 3)
??????? find(:all, :limit => limit)
??? end
end
單表繼承:?
優點:? 這樣做的好處是提高讀取表的速度,因為沒有關聯,只有一個表。
缺點:? 當各個子類的相似的地方很少的時候,會導致表中有很多屬性,這樣處理這個問題的方法是用多態關聯。
多態關聯:
types表中的多態外鍵如果是duotai,那么表的屬性是duotai_id, duotai_type,一個記錄鍵值,一個記錄類名。
class Article < ActiveRecord::Base
??? has_one :type, :as => :duotai
end
class Image < ActiveRecord::Base
??? has_one :type, :as => :duotai
end
class Type < ActiveRecord::Base
??? belongs_to :duotai, :polymorphic => true
end
自引用的連接:
class Employee < ActiveRecord::Base
? belongs_to :boss, :class_name => "Employee", :foreign_key => :employee_id
end
預先讀取子記錄
以下實例如果沒有:include => :people, infos為n, 那么他將執行2n+1次,如果指定了:include,將預加載與info有關的people記錄,此時將提高效率,但是如果預加載了數據,但沒有用這些數據,反而會降低效率。
Benchmark.bm() do |x|
??? x.report{
??????? infos = Info.find(:all, :include => :people)
??????? infos.each do |info|
??????????? info.people.name
??????? end
??? }
end
如果一個對象剛剛創建出來,還沒有與數據庫記錄建立映射,我們稱它為新對象(new records)。調用new_records?
模型驗證:
validate、 validate_on_create、 validate_on_update
ActiveRecord::Errors
[]? info.errors[:email]
on? info.errors.on(:email)
add(:屬性, 信息)
size、length、count
each、each_error? 迭代錯誤屬性和錯誤屬性對應的信息
each_full? 迭代錯誤信息
full_messages? 錯誤信息組成的數組
invalid?(屬性)? 如果屬性無效,則返回true
to_xml
empty?
ActiveRecord::Errors.default_error_messages? 這個返回所有的默認信息,如果修改默認信息的話,可以從這里修改。
回調:
創建方式
1:直接在回調中寫代碼。
2:聲明回調處理器,處理器可以是一個代碼塊也可以是一個方法,如果用方法作為一個處理器,應該被聲明為private或protected。
eg
def before_save
? ...
end
before_save :check
private
def check
end
注意:以下方法將跳過回調
??? * decrement
??? * decrement_counter
??? * delete
??? * delete_all
??? * find_by_sql
??? * increment
??? * increment_counter
??? * toggle
??? * update_all
??? * update_counters
ActiveRecord::Base
column_names:? 所有列名組成的數組
columns:? 所有包含列信息的對象組成的數組。
columns_hash:?? 列名與列對象組成的hash數組。
實例方法:
attributes:? 所有屬性和屬性值組成的hash數組。
attributes=
attribute_names:? 所有屬性組成的數組。
attribute_present?(屬性名稱) 如果屬性名稱存在,則返回true,反之亦然。
事務: 要么全部執行,要么全部不執行。
模型類.transaction do
end
begin ... rescue ...end
eg:
class Info < ActiveRecord::Base
? def validate
??? errors.add(:age, "age is not less than 0") if age < 0
? end
? def jian(i)
??? self.money = self.money - i
??? self.save!
? end
end
info = Info.create!(:money => 100)
begin
Info.transaction do; info.jian(200); end
rescue
end
puts info.money?? =》 -100
該實例中要求money不能小于0,而我們也做到了,表中的數據不會被改,但是info.money 返回的值是-100,模型對象的值被該變了,這是因為ActiveRecord沒有跟綜對象在事務前后的狀態,我們可以指定事務跟蹤哪些模型對象。
Info.transaction(info) do; .... end,此時輸出的值就是100了。
路由:
map.connect 重要參數
:requirements => {:name => /regexp/}? 要求url中特定的組成部分與指定的正則表達式一一匹配。
:defaults => {:name => "value", ...}? 設定各組成部分的默認值
:conditions => {:name => /regexp/orstring,...}? 設定路由的條件
:name => value? 設定:name參數的默認值
eg:
map.connect 'infos/:year', :controller => "infos", :action => "hello", :defaults => {:year => 2008},:requirements => {:year => /(19|20)\d\d/}, :conditions => {:method => :get}
注意:
map.connect "*aa", :controller => "", :action => ""
符合任何的url格式,但是一定要注意的是要放在最后,否則其他的路由都無法匹配了。
有名路由
map.hello "hello/:id", :controller => "infos", :action => "index"
1>? hello_url(:id => 1)或hello_url :controller => "infos", :action => "index"
可以訪問這個url。
注意: 以上url可以用path替代。
2>? 地址欄中可以輸入hello訪問這個url。
資源路由:
map.resources :articles, :collection => {:recent => :get}, :member => {:release => :put}, :new => {:hello => :get}
增加以下規則:
recent_articles_path
release_article_path(:id => 1)
hello_new_article_path
map.resources :articles do |article|
? article.resources :comments
end
articles/99/comments/4
控制器環境(可以在action中直接引用)
controller_name:? controller名稱
action_name:? action名稱
session: session
cookies: cookie
params: 存放著參數的hash對象
rsponse
request: 進入控制器的請求對象,包含屬性。
? domain: 請求地址域名部分的最后兩端。
? remote_ip: 客戶端的ip地址。
? env: 返回請求的環境。
? get?、post?、put?、delete?、head?
? method:? 返回客戶端訪問所使用的請求方法。
? xhr?或xml_http_request?? 如果請求來自AJAX的輔助方法,則返回true,否則返回false。
控制器應答:
1:渲染一個模板,最常見的(.html、 .rxml、 .rjs)。
2:返回一個字符串給瀏覽器,主要用于發送錯誤提示。
3:發送html以外的數據,這種方式通常用于提供下載。
控制器每次只響應一個請求:
render、 redirect_to、 send_xxx
1> render :action
2> render :template
3> render :file
4> render :partial? 調用局部模板
:object 指定傳遞給局部模板的對象。
5> render
ml
6> render :nothing
7> render :inline
8> render :text
9> render(:update) do |page| ... end
重要參數:
:locals => {},指定模板要使用的局部變量。
:layout => false|nil|true|模板名稱。
render_to_string 可以當作render使用,不過它不會跳轉,只會把整個的內容作為字符串返回。
method_missing:調用指定的action名稱無效時,method_missing會渲染一個內聯的模板,將action的名稱和請求參數顯示出來。
eg:
? def method_missing(name, *args)
??? render(:inline => %{<h2> Unknown action: #{name}</h2>
??? Here are the request parameters:<br/>
??? <%= debug(params) %>})
? end
send_data(data, options)? 發送一個數據流給客戶端。
參數:
:filename、 disposition(inline|attachment)、status、type
send_file(path, options)? 發送一個文件給客戶端
參數:
:filename、 :disposition、 :status、 :type、 buffer_size、 stream
重定向:
redirect_to(:action => "")
redirect_to(path)
redirect_to(:back)? 返回上一頁,注意:如果redirect_to(:back)寫在了index的action中,并且訪問index的時候能夠直接運行redirect_to(:back),則不能直接訪問index的action,因為他會跳轉上一頁,但是沒有上一頁。
過濾器:
prepend_before_filter
before_filter、append_before_filter
prepend_after_filter
after_filter、append_before_filter
參數:
:only、 :except
定義過濾器的方式:
1:
before_filter do
? ...
end
2:
before_filter :hello,
nly => [:show, :index]
skip_filter、 skip_before_filter、skip_after_filter
參數:
:only、 :except
緩存:
片段緩存、 頁面緩存、 action緩存
caches_page、 caches_action、 cache do .... end
默認配置下,cache只有在產品環境下才生效,如果要在開發環境下生效,要配置以下信息中的一條。(config/environments/development.rb)
ActionController::Base.perform_caching = true|false
config.action_controller.perform_caching = true
解除緩存:
expire_action、 expire_page、 expire_fragment :controller => "...", :action => "..."
1》默認:緩存片段的名字取決于渲染該頁面的控制器名稱和action名稱,所以使用expire_fragment指定控制器名稱和action名稱來是對應的片段緩存失效。
2》指定緩存名稱(等同于url_for的參數)
緩存存儲機制的全局設置(environment.rb設置):
緩存目錄:
config.action_controller.page_cache_directory = RAILS_ROOT + "/public/caches"
緩存類型:
config.action_controller.page_cache_extension = ".html"
缺點:導致大量的數據從網絡驅動器傳輸到某一臺具體的web服務器,然后將這些數據發送給用戶,所以,如果在高吐量的網站中使用這種存儲機制,服務器之間的網絡寬帶應該非常寬。
緩存存儲體系只對action緩存和片段有效,全頁面緩存必須以文件的形式放在public目錄下。
頁面緩存是最快速的一種緩存應用。那么應該在什么時候使用他呢?
1、對于所有用戶都相同的頁面
2、公開的頁面,沒有用戶認證的頁面
緩存分頁:
因為頁面緩存的時候會忽略掉像/blog /list?page=2這樣的參數,所以你需要使用/blog/list/2這樣的地址形式,而原來我們使用的是id保存參數值,現在我們需要用 page來保存參數值。
下面我們修改 /config/routes.rb文件
map.connect 'blog/list/:page',
??? :controller => 'blog',
??? :action => 'list',
??? :requirements => { :page => /\d+/},
??? :page => nil
使用了新的routes定義,我們的連接也應該改成
<%= link_to "Next Page", :controller => 'blog', :action => 'list', :page => 2 %>
最終的連接結果是"/blog/list/2",當我們點這個連接的時候,后臺會處理兩件事情
1、應用將2放入page這個參數中,而不是原來id這個參數
2、緩存將生成 /public/blog/list/2.html 這個頁面
所以,緩存分頁,就要將頁面參數變成頁面的一部分,而不要使用地址參數的形式,他是會被忽略的。
解決危險鏈接的方式:
1:使用表單和按鈕(button_to)
2:使用確認頁面
link_to、link_to_if、link_to_unless、button_to
stylesheet_link_tag
javascript_include_tag:?? 假設文件在public/javascripts目錄
對象調用屬性:
eg: info.name 或 info["name"]
form_for、 form_tag
form_for(:info, @info, :url => {:action => "create"}, :html => {:method => "post"}
:info?? 告訴rails正在操作哪個模型類的對象
@info?? 通過哪個實例變量獲得該對象
:url??? 訪問的action地址
:html?? 定義訪問的方法,可以定義:multipart => true,上傳。
select標簽:
1>collection_select(:post, :author_id, Author.all, :id, :name_with_initial, {:prompt => true})
2>select、select_tag "people", "<option>David</option>"
3>options_from_collection_for_select(@people, 'id', 'name')
4>options_for_select({ "Basic" => "$20", "Plus" => "$40" }, "$40")
子表單:
<% fields_for :name, @info.name do |field| %>
? Name: <%= field.text_field :name %>
<% end %>
卸載layout頁面中:
<% content_for :head do %>
? <ul><li>a</li><li>b</li></ul>
<% end %>
<%= yield :head %>
發送郵件:
config.action_mailer.delivery_method = :smtp|:sendmail|:test
開發環境下默認的設置是:smtp。
:smtp、:sendmail 可以讓ActionMailer發送郵件。
:test 可以用于單元測試和功能測試,電子郵件不會發送出去,而是被放入一個數組。
禁止開發環境下發送郵件:
config/environments/development.rb中設置config.action_mailer.delivery_method = :test
config.action_mailer.perform_deliveries = true|false
perform_deliveries為true,郵件被正常發送,否則不發送,用于測試。
config.action_mailer.raise_delivery_errors = true|false
設置郵件發送過程中的異常是否拋還給應用程序。false為忽略,true為拋還。
config.action_mailer.default_charset = "utf-8"
設置發送郵件的字符集。
ActionMailer::Base.smtp_settings = {
??? :address => "smtp.163.com",:port => 25,:domain => ".com",??? :authentication => :login,:user_name => "zhangcaiyan0123@163.com",:password => "zhangcaiyan",}
設置smtp服務器(其中domain是域名稱)
ruby script/generate mailer OrderMailer confirm sent
模型中定義方法:
? def confirm(sent_at = Time.now)
??? subject??? '標題'
??? recipients "zhangcaiyanbeyond@gmail.com"
??? from?????? 'zhangcaiyan0123@163.com'
??? sent_on??? sent_at
??? body?????? "郵件正文"
? end
bcc????????? 暗送
cc?????????? 抄送
charset??????? 默認為smtp_settings中的default_charset屬性
subject??????? 標題
from??????? 發件人的郵箱
recipients???? 收件人的郵箱
body??????? 正文
send_on???? 發送時間
headers??????? 指定郵件的頭信息
attachment(上傳插件) :filename => 文件名稱, :body => 文件內容(file.read), :content_type => "內容類型"
OrderMailer.deliver_confirm?? 發送郵件
email = OrderMailer.create_confirm??? 創建郵件對象(TMail::Mail對象)
OrderMailer.deliver(email)
注意:? OrderMailer是模型類,create_confirm中的create是表示要創建對象,confirm是表示模型類中的方法,deliver表示要發送郵件。
保護rails應用:
防御sql注入攻擊:
eg:這個實例就是惡意注入的例子,其中1為true,他會查處表中的所有數據。
Core::User.find(:all, :conditions => "id > '' or 1")
防止惡意注入:
絕對不要用ruby的#{...}機制直接把字符串插入到sql語句中,而應該用Rails提供的變量綁定。
eg:
Core::User.find(:all, :conditions => ["id > ?", 3])
Core::User.find(:all, :conditions => ["id > :id", {:id => 3}])
用參數直接創建記錄:
User.create(params[:user])
為了防止用戶模擬一些屬性提交,我們可以將某些屬性保護起來。
attr_protected? :屬性1, :屬性2? 列出被保護的屬性
attr_accessible :屬性1, :屬性2? 列出允許自動賦值的屬性,也就是說除此之外的都是被保護的屬性
被保護的屬性也就是不能通過create(params[:user])直接保存,而是需要通過賦值才可以。eg:
user = User.new
user.role = params[:role]
user.save
不要相信ID參數:
當我們通過id查找出數據,然后對數據進行操作時,我們要注意某些情況:例如當我們瀏覽(/show/id)某個用戶的數據時,可以利用url瀏覽其他用戶的數據,為了防止這樣的事發生,可以這樣:
eg:
1》 order = Order.find(params[:id], :conditions => ["user_id = ?", user_id])
2》 order = @user.orders.find(id)
3》 order = @user.orders.find(id).destroy
防御XSS攻擊:
攻擊者把自己編寫的javascript腳本放進網頁,來獲得他們想要的cookie,我們可以通過rails提供的h(string)輔助方法(實際上是html_escape()方法的別名)
生成rails項目的HTML文檔
rake doc:app
ActiveRecord::Errors.default_error_messages = hash
修改默認錯誤顯示信息
named_scope的使用:
named_scope :quanbu, :conditions => ["name=zcy"]
named_scope
ianzhi, :lambda{|limit|{:limit = limit}}
Shili.quanbu.xianzhi(3)
顯示錯誤頁面:? 當指定的異常發生時,將顯示特定的頁面,這個最好放到application_controller中
rescue_from? 異常, :with => :action
eg:
rescue_from Exception, :with => :error
def error
? render :file => "novel/infos/error", :layout => "novel"
end
對于boolean類型的數據,應該省略前面的is_,ActiveRecord會自動加個?號,映射成actived? ,不是boolean型的數據也會也會擴展?
_form下的共享表單,區間的情況
1:map.namespace :doctor do |doctor|
??? doctor.resources :patients
end
["doctor", @patient ]
2:map.resources :doctor do |doctor|
??? doctor.resources :patients
end
[@doctor, @patient ]
ruby script/server -e development(默認)
ruby script/server -e test
ruby script/server -e production
在編寫ruby代碼時,如果要引用另一個文件中的類和模塊,需要使用require關鍵字,但是當我們在rails中引用另一個文件中的類和模塊時,rails會自動把類名稱根據命名約定改為文件名,然后在同一目錄下加載該文件。
按模塊組織控制器:
ruby script/generate controller Admin::Book action1 action2
admin模塊下的book_controller控制器
Rails給Enumerable類擴展的方法
1》 group_by: 將一個對象集合分組,針對每個對象調用塊,然后根據代碼塊的返回值作為分組的鍵,值是所有擁有同一個鍵的對象組成的數組。
eg:
User.all.group_by{|user| user.sex}
User.all.group_by(&:name)
2》 sum: 對集合進行加總,把每個元素傳遞給一個代碼塊,并對代碼塊返回的值進行累加。
User.all.sum(&:id) 返回所有user對象的id的和
3》 in_groups_of(arg1, arg2)? 將某一個數組分為子元素由arg1個元素組合的數組元素組成的數組,出現無法填充的值由arg2填補。
eg:
[1,2,3,4,5].in_groups_of(2,"blank")???? =>?????
[[1,2],[3,4],[5,"blank"]]
字符串擴展
str[0] 第一個字符的Ascill碼。
str[2..3] 返回字符串的第三個字符開始的3個字符組成的字符串。
str.at(0) 第一個字符
str.to(4) 前5個字符組成的字符串
str.from(4) 最后5個字符組成的字符串
str.first
str.last
str.starts_with?(字符串)
str.ends_with?(字符串)
str.each_char{|char| char.upcase}
str.pluralize 復數形式
str.singularize? 單數形式
str.humanize
str.titleize
對數值的擴展:
figure.ordinalize?? 返回數字的序數形式
figure.bytes、kilobytes、megabytes、gigabytes、terabytes、
perabytes、exabyte? 數據大小
figure.seconds、minutes、hours、days、weeks、fortnights、months、years? 時間
注意:? ago、 until、 from_now、 since
eg:?
1.day.ago
1.day.ago(Time.now)
時間和日期的擴展
now = Time.now
now.to_s(:short)、to_s(:db)、to_s(:long)、to_s(:rfc822)
now.ago(2.days)、since(2.days)
change(:hour => 12)? 改變日期的hour為12
advance(:hour => 12)? 推遲日期的12hour
to_date、to_time
at_beginning_of_week、at_beginning_of_month、at_beginning_of_quarter(季)、at_beginning_of_year
ruby符號的擴展:
posts.group_by{|post| post.author_id}
posts.group_by(&:author_id)
with_options的使用:
Rails里有些方法使用一個Hash作為最后一個可選的參數,如果對多個方法有同樣的選項,我們可以使用with_options來減少冗余:
eg:
with_options :if => :should_validate_password? do |user|?
? user.validates_presence_of :password?
? user.validates_confirmation_for :password?
? user.validates_format_of :password, :with => /^[^\s]+$/
end
遷移任務:
create_table??
:force => true? 如果表存在,強制刪除,然后再創建表
:temporary => true? 創建一張臨時表,程序與數據庫斷開鏈接,則表被刪除。
:options => "xxxx"? 指定針對于底層數據庫的選項,這些選項會被加到create table語句的后面
:primary_key 主鍵
:id => false? 沒有主鍵的表
如果遷移任務 提供的方法 不夠滿足你 的需要,也 可以使用數 據庫專有的 功能:使用execute() 方法就可以運行原生 SQL 語句。例如:給表加上外鍵
class CreateLineItems < ActiveRecord::Migration
??? def self.up
????? create_table :line_items do |t|
??????? t.column :product_id, :integer
??????? t.column

????? end
????? execute "alter table line_items
????????? add constraint fk_line_item_products
????????? foreign key (product_id) references products(id)"
??? end
???? def self.down
????? drop_table :line_items
???? end
end
ActiveRecord::Base
column_names? 屬性組成的數組
columns_hash["屬性名稱"]? 屬性名稱信息
屬性_before_type_cast? 讀取屬性時,ActiveRecod會盡量將得到的值轉型成適當的ruby類型,如果我們希望的到屬性的原始值,可以在屬性名稱后面加上before_type_cast。
eg:User.first.created_at??? =>?? 2010-06-24 09:41:17
連接數據庫:? ActiveRecord::Base.establish_connection(:adapter => "mysql", :host => "localhost", :database => "rails", :username => "root", :password => "1234")
防止惡意注入:
1> 問號占位符:?? User.find(:all, :conditions => ["id > ?", 3]
2> 命名占位符:?? User.find(:all, :conditions => ["id > :id", {:id => 3}])
注意:
命名占位符的語句可以轉換為
User.find(:all, :conditions => ["id > :id", params[:user]])
獲取字段統計信息:
average:?
maximum:
minimum:
sum? :
count? :
以上方法的參數:?
:conditions、:joins、:limit、:order、:having、:select、 :distinct
eg:
Order.maximum :amount, :group => "state", :limit => 3,

擁有訂單最大的三個州
更新操作:
update_attribute、update_attributes、update、update_all
創建操作:
create、create!、save、save!
刪除數據:
delete、delete_all、destroy、destroy_all
delete繞過了ActiveRecord的回調和驗證,destory沒有繞過回調和驗證
序列化數據:
serialize :屬性
序列化的屬性可以直接存入Array和hash類型的數據,也可以直接讀出來使用
缺點:
ruby應用之外的應用訪問序列化的數據時,除非它能夠理解yaml格式,否則無法獲取這個字段的信息。
彌補這種缺點的方式是用對象聚合的方式來實現類似的效果
聚合/組合:
聚合可以把一個或多個屬性封裝為一個類,然后這個類里可以添加操作屬性的方法,這樣我們就可以實現序列化所要實現的目的了,而且可以避免序列化的缺點。
composed_of :attr_name, :class_name => 類名稱, :mapping => [字段與屬性組成的數組]
eg:
class Xingxi < ActiveRecord::Base
? composed_of :inf, :class_name => "Inf", :mapping => [[:name, :name], [:phone, :phone]]
end
class Inf
??? attr_reader :name, :phone
??? def initialize(name, phone)
??????? @name = name
??????? @phone = phone
??? end
??? def to_s
????? [@name, @phone].compact.join(" ")
??? end
end
inf = Inf.new("zcy",? "12344454")
Xingxi.create(:inf => inf)
注意:
教程上指出? :class_name對應的“類名稱”可以是類常量,也可以是包含類常量的字符串,但實際上只能是包含類常量的字符串,如果類名恰好是屬性名的混合大寫形式,那么class_name可以省略,但是實際上不可以,包括:mapping也不可以。
關聯:
class Line < ActiveRecord::Base
? belongs_to :product
end
belongs_to :product? 會產生以下方法
1>:product(force_reload=false) 返回關聯的product對象,默認情況下product對象會被緩存,當force_reload=true時,將重新查詢數據庫。
2>:product=: line對象和product對象關聯起來,將line記錄的外鍵值設為product的主鍵值,如果product沒有保存,line保存的時候會保存product,包括外鍵。
3>:build_product(attributes={}) 新建一個product對象,用指定的屬性對其初始化,相當于product=Product.new(attributes)。
4>:build_create(attributes={}) 創建一個product對象,與line關聯,保存product對象。
order:? has_one中也有order,主要用于例如最后一個***,此時便可以用order指定排序。
:dependent?? :destroy(true)、:nullify、 false
??? :destroy?? 刪除記錄的同時也刪除子記錄
??? :nullify?? 刪除記錄的同時刪除子記錄的外鍵
??? false????? 只刪除記錄
has_many :lines
class Product < ActiveRecord::Base
? has_many :lines
end
has_many :lines? 會產生以下方法
lines(force_reload=false)? 同上
lines.build(attributes = {})
lines.create(attributes = {})
lines << line? 將當前line對象添加到lines對象數組里
lines.push(line對象) line對象添加到lines
lines.delete(line,...) 刪除一個或多個line對象,如果關聯為:destroy => :destroy,子對象被刪除,否則只是刪除子對象的外鍵,打斷與父對象的關聯。
lines.delete_all? 調用所有子對象的delete方法
lines.destroy_all?? 調用所有子對象的destroy方法
lines.clear? 和delete一樣,不同的是clear針對的是所有的子對象。
lines.find(options)
lines.count(options)
lines.size
lines.length? 強制加載所有子對象,返回對象的集合。
lines.empty?
lines.replace(line對象數組)? line對象數組替換原先的lines
lines.sum(options) 不便利內存中的子對象集合,直接在數據庫端操作
lines.uniq? 返回一個數組,包含所有具備獨立id的子對象
1> finder_sql: 重新定義了統計子記錄的sql語句
?? counter_sql: 重新定義了統計子記錄的數目
注意: 如果指定了finder_sql而沒有指定counter_sql,finder_sql中的子句會被替換為select count(*),然后記錄子記錄的數量。
eg:
has_many

作用: 當:conditions無法滿足時,:finder_sql顯的非常重要。
:order : 以特定的順序排列
:conditions : 返回符合條件的子記錄
:dependent?? :destroy、:nullify、 false
??? :destroy?? 刪除記錄的同時也刪除子記錄
??? :nullify?? 刪除記錄的同時刪除子記錄的外鍵
??? false????? 只刪除記錄
多對多的關聯有兩種
1: 利用默認的關聯表
2:自己創建關聯表,利用關聯中的:through
:through?? 告訴rails通過guanlians表來導航關聯
:source? 用來指定關聯在那個屬性上
:uniq => true? 去掉重復的對象 等同于 :select => "distinct books.*"
eg:
class Kind < ActiveRecord::Base
??? has_many :guanlians
??? has_many :readers, :through => :guanlians, :source => :book
end
注意:
has_many :reader1s,:conditions => "guanlians.cishu > 0"
當使用conditions不能很好的表達時,無法提供參數,可以考慮以下格式,而且當同樣的方法被多次調用時,可以將方法寫在模塊中,然后在關聯中:extend => "模塊名稱" 來調用。
has_many :readers do
??? def reader(limit = 3)
??????? find(:all, :limit => limit)
??? end
end
單表繼承:?
優點:? 這樣做的好處是提高讀取表的速度,因為沒有關聯,只有一個表。
缺點:? 當各個子類的相似的地方很少的時候,會導致表中有很多屬性,這樣處理這個問題的方法是用多態關聯。
多態關聯:
types表中的多態外鍵如果是duotai,那么表的屬性是duotai_id, duotai_type,一個記錄鍵值,一個記錄類名。
class Article < ActiveRecord::Base
??? has_one :type, :as => :duotai
end
class Image < ActiveRecord::Base
??? has_one :type, :as => :duotai
end
class Type < ActiveRecord::Base
??? belongs_to :duotai, :polymorphic => true
end
自引用的連接:
class Employee < ActiveRecord::Base
? belongs_to :boss, :class_name => "Employee", :foreign_key => :employee_id
end
預先讀取子記錄
以下實例如果沒有:include => :people, infos為n, 那么他將執行2n+1次,如果指定了:include,將預加載與info有關的people記錄,此時將提高效率,但是如果預加載了數據,但沒有用這些數據,反而會降低效率。
Benchmark.bm() do |x|
??? x.report{
??????? infos = Info.find(:all, :include => :people)
??????? infos.each do |info|
??????????? info.people.name
??????? end
??? }
end
如果一個對象剛剛創建出來,還沒有與數據庫記錄建立映射,我們稱它為新對象(new records)。調用new_records?
模型驗證:
validate、 validate_on_create、 validate_on_update
ActiveRecord::Errors
[]? info.errors[:email]
on? info.errors.on(:email)
add(:屬性, 信息)
size、length、count
each、each_error? 迭代錯誤屬性和錯誤屬性對應的信息
each_full? 迭代錯誤信息
full_messages? 錯誤信息組成的數組
invalid?(屬性)? 如果屬性無效,則返回true
to_xml
empty?
ActiveRecord::Errors.default_error_messages? 這個返回所有的默認信息,如果修改默認信息的話,可以從這里修改。
回調:
創建方式
1:直接在回調中寫代碼。
2:聲明回調處理器,處理器可以是一個代碼塊也可以是一個方法,如果用方法作為一個處理器,應該被聲明為private或protected。
eg
def before_save
? ...
end
before_save :check
private
def check
end
注意:以下方法將跳過回調
??? * decrement
??? * decrement_counter
??? * delete
??? * delete_all
??? * find_by_sql
??? * increment
??? * increment_counter
??? * toggle
??? * update_all
??? * update_counters
ActiveRecord::Base
column_names:? 所有列名組成的數組
columns:? 所有包含列信息的對象組成的數組。
columns_hash:?? 列名與列對象組成的hash數組。
實例方法:
attributes:? 所有屬性和屬性值組成的hash數組。
attributes=
attribute_names:? 所有屬性組成的數組。
attribute_present?(屬性名稱) 如果屬性名稱存在,則返回true,反之亦然。
事務: 要么全部執行,要么全部不執行。
模型類.transaction do
end
begin ... rescue ...end
eg:
class Info < ActiveRecord::Base
? def validate
??? errors.add(:age, "age is not less than 0") if age < 0
? end
? def jian(i)
??? self.money = self.money - i
??? self.save!
? end
end
info = Info.create!(:money => 100)
begin
Info.transaction do; info.jian(200); end
rescue
end
puts info.money?? =》 -100
該實例中要求money不能小于0,而我們也做到了,表中的數據不會被改,但是info.money 返回的值是-100,模型對象的值被該變了,這是因為ActiveRecord沒有跟綜對象在事務前后的狀態,我們可以指定事務跟蹤哪些模型對象。
Info.transaction(info) do; .... end,此時輸出的值就是100了。
路由:
map.connect 重要參數
:requirements => {:name => /regexp/}? 要求url中特定的組成部分與指定的正則表達式一一匹配。
:defaults => {:name => "value", ...}? 設定各組成部分的默認值
:conditions => {:name => /regexp/orstring,...}? 設定路由的條件
:name => value? 設定:name參數的默認值
eg:
map.connect 'infos/:year', :controller => "infos", :action => "hello", :defaults => {:year => 2008},:requirements => {:year => /(19|20)\d\d/}, :conditions => {:method => :get}
注意:
map.connect "*aa", :controller => "", :action => ""
符合任何的url格式,但是一定要注意的是要放在最后,否則其他的路由都無法匹配了。
有名路由
map.hello "hello/:id", :controller => "infos", :action => "index"
1>? hello_url(:id => 1)或hello_url :controller => "infos", :action => "index"
可以訪問這個url。
注意: 以上url可以用path替代。
2>? 地址欄中可以輸入hello訪問這個url。
資源路由:
map.resources :articles, :collection => {:recent => :get}, :member => {:release => :put}, :new => {:hello => :get}
增加以下規則:
recent_articles_path
release_article_path(:id => 1)
hello_new_article_path
map.resources :articles do |article|
? article.resources :comments
end
articles/99/comments/4
控制器環境(可以在action中直接引用)
controller_name:? controller名稱
action_name:? action名稱
session: session
cookies: cookie
params: 存放著參數的hash對象
rsponse
request: 進入控制器的請求對象,包含屬性。
? domain: 請求地址域名部分的最后兩端。
? remote_ip: 客戶端的ip地址。
? env: 返回請求的環境。
? get?、post?、put?、delete?、head?
? method:? 返回客戶端訪問所使用的請求方法。
? xhr?或xml_http_request?? 如果請求來自AJAX的輔助方法,則返回true,否則返回false。
控制器應答:
1:渲染一個模板,最常見的(.html、 .rxml、 .rjs)。
2:返回一個字符串給瀏覽器,主要用于發送錯誤提示。
3:發送html以外的數據,這種方式通常用于提供下載。
控制器每次只響應一個請求:
render、 redirect_to、 send_xxx
1> render :action
2> render :template
3> render :file
4> render :partial? 調用局部模板
:object 指定傳遞給局部模板的對象。
5> render

6> render :nothing
7> render :inline
8> render :text
9> render(:update) do |page| ... end
重要參數:
:locals => {},指定模板要使用的局部變量。
:layout => false|nil|true|模板名稱。
render_to_string 可以當作render使用,不過它不會跳轉,只會把整個的內容作為字符串返回。
method_missing:調用指定的action名稱無效時,method_missing會渲染一個內聯的模板,將action的名稱和請求參數顯示出來。
eg:
? def method_missing(name, *args)
??? render(:inline => %{<h2> Unknown action: #{name}</h2>
??? Here are the request parameters:<br/>
??? <%= debug(params) %>})
? end
send_data(data, options)? 發送一個數據流給客戶端。
參數:
:filename、 disposition(inline|attachment)、status、type
send_file(path, options)? 發送一個文件給客戶端
參數:
:filename、 :disposition、 :status、 :type、 buffer_size、 stream
重定向:
redirect_to(:action => "")
redirect_to(path)
redirect_to(:back)? 返回上一頁,注意:如果redirect_to(:back)寫在了index的action中,并且訪問index的時候能夠直接運行redirect_to(:back),則不能直接訪問index的action,因為他會跳轉上一頁,但是沒有上一頁。
過濾器:
prepend_before_filter
before_filter、append_before_filter
prepend_after_filter
after_filter、append_before_filter
參數:
:only、 :except
定義過濾器的方式:
1:
before_filter do
? ...
end
2:
before_filter :hello,

skip_filter、 skip_before_filter、skip_after_filter
參數:
:only、 :except
緩存:
片段緩存、 頁面緩存、 action緩存
caches_page、 caches_action、 cache do .... end
默認配置下,cache只有在產品環境下才生效,如果要在開發環境下生效,要配置以下信息中的一條。(config/environments/development.rb)
ActionController::Base.perform_caching = true|false
config.action_controller.perform_caching = true
解除緩存:
expire_action、 expire_page、 expire_fragment :controller => "...", :action => "..."
1》默認:緩存片段的名字取決于渲染該頁面的控制器名稱和action名稱,所以使用expire_fragment指定控制器名稱和action名稱來是對應的片段緩存失效。
2》指定緩存名稱(等同于url_for的參數)
緩存存儲機制的全局設置(environment.rb設置):
緩存目錄:
config.action_controller.page_cache_directory = RAILS_ROOT + "/public/caches"
緩存類型:
config.action_controller.page_cache_extension = ".html"
缺點:導致大量的數據從網絡驅動器傳輸到某一臺具體的web服務器,然后將這些數據發送給用戶,所以,如果在高吐量的網站中使用這種存儲機制,服務器之間的網絡寬帶應該非常寬。
緩存存儲體系只對action緩存和片段有效,全頁面緩存必須以文件的形式放在public目錄下。
頁面緩存是最快速的一種緩存應用。那么應該在什么時候使用他呢?
1、對于所有用戶都相同的頁面
2、公開的頁面,沒有用戶認證的頁面
緩存分頁:
因為頁面緩存的時候會忽略掉像/blog /list?page=2這樣的參數,所以你需要使用/blog/list/2這樣的地址形式,而原來我們使用的是id保存參數值,現在我們需要用 page來保存參數值。
下面我們修改 /config/routes.rb文件
map.connect 'blog/list/:page',
??? :controller => 'blog',
??? :action => 'list',
??? :requirements => { :page => /\d+/},
??? :page => nil
使用了新的routes定義,我們的連接也應該改成
<%= link_to "Next Page", :controller => 'blog', :action => 'list', :page => 2 %>
最終的連接結果是"/blog/list/2",當我們點這個連接的時候,后臺會處理兩件事情
1、應用將2放入page這個參數中,而不是原來id這個參數
2、緩存將生成 /public/blog/list/2.html 這個頁面
所以,緩存分頁,就要將頁面參數變成頁面的一部分,而不要使用地址參數的形式,他是會被忽略的。
解決危險鏈接的方式:
1:使用表單和按鈕(button_to)
2:使用確認頁面
link_to、link_to_if、link_to_unless、button_to
stylesheet_link_tag
javascript_include_tag:?? 假設文件在public/javascripts目錄
對象調用屬性:
eg: info.name 或 info["name"]
form_for、 form_tag
form_for(:info, @info, :url => {:action => "create"}, :html => {:method => "post"}
:info?? 告訴rails正在操作哪個模型類的對象
@info?? 通過哪個實例變量獲得該對象
:url??? 訪問的action地址
:html?? 定義訪問的方法,可以定義:multipart => true,上傳。
select標簽:
1>collection_select(:post, :author_id, Author.all, :id, :name_with_initial, {:prompt => true})
2>select、select_tag "people", "<option>David</option>"
3>options_from_collection_for_select(@people, 'id', 'name')
4>options_for_select({ "Basic" => "$20", "Plus" => "$40" }, "$40")
子表單:
<% fields_for :name, @info.name do |field| %>
? Name: <%= field.text_field :name %>
<% end %>
卸載layout頁面中:
<% content_for :head do %>
? <ul><li>a</li><li>b</li></ul>
<% end %>
<%= yield :head %>
發送郵件:
config.action_mailer.delivery_method = :smtp|:sendmail|:test
開發環境下默認的設置是:smtp。
:smtp、:sendmail 可以讓ActionMailer發送郵件。
:test 可以用于單元測試和功能測試,電子郵件不會發送出去,而是被放入一個數組。
禁止開發環境下發送郵件:
config/environments/development.rb中設置config.action_mailer.delivery_method = :test
config.action_mailer.perform_deliveries = true|false
perform_deliveries為true,郵件被正常發送,否則不發送,用于測試。
config.action_mailer.raise_delivery_errors = true|false
設置郵件發送過程中的異常是否拋還給應用程序。false為忽略,true為拋還。
config.action_mailer.default_charset = "utf-8"
設置發送郵件的字符集。
ActionMailer::Base.smtp_settings = {
??? :address => "smtp.163.com",:port => 25,:domain => ".com",??? :authentication => :login,:user_name => "zhangcaiyan0123@163.com",:password => "zhangcaiyan",}
設置smtp服務器(其中domain是域名稱)
ruby script/generate mailer OrderMailer confirm sent
模型中定義方法:
? def confirm(sent_at = Time.now)
??? subject??? '標題'
??? recipients "zhangcaiyanbeyond@gmail.com"
??? from?????? 'zhangcaiyan0123@163.com'
??? sent_on??? sent_at
??? body?????? "郵件正文"
? end
bcc????????? 暗送
cc?????????? 抄送
charset??????? 默認為smtp_settings中的default_charset屬性
subject??????? 標題
from??????? 發件人的郵箱
recipients???? 收件人的郵箱
body??????? 正文
send_on???? 發送時間
headers??????? 指定郵件的頭信息
attachment(上傳插件) :filename => 文件名稱, :body => 文件內容(file.read), :content_type => "內容類型"
OrderMailer.deliver_confirm?? 發送郵件
email = OrderMailer.create_confirm??? 創建郵件對象(TMail::Mail對象)
OrderMailer.deliver(email)
注意:? OrderMailer是模型類,create_confirm中的create是表示要創建對象,confirm是表示模型類中的方法,deliver表示要發送郵件。
保護rails應用:
防御sql注入攻擊:
eg:這個實例就是惡意注入的例子,其中1為true,他會查處表中的所有數據。
Core::User.find(:all, :conditions => "id > '' or 1")
防止惡意注入:
絕對不要用ruby的#{...}機制直接把字符串插入到sql語句中,而應該用Rails提供的變量綁定。
eg:
Core::User.find(:all, :conditions => ["id > ?", 3])
Core::User.find(:all, :conditions => ["id > :id", {:id => 3}])
用參數直接創建記錄:
User.create(params[:user])
為了防止用戶模擬一些屬性提交,我們可以將某些屬性保護起來。
attr_protected? :屬性1, :屬性2? 列出被保護的屬性
attr_accessible :屬性1, :屬性2? 列出允許自動賦值的屬性,也就是說除此之外的都是被保護的屬性
被保護的屬性也就是不能通過create(params[:user])直接保存,而是需要通過賦值才可以。eg:
user = User.new
user.role = params[:role]
user.save
不要相信ID參數:
當我們通過id查找出數據,然后對數據進行操作時,我們要注意某些情況:例如當我們瀏覽(/show/id)某個用戶的數據時,可以利用url瀏覽其他用戶的數據,為了防止這樣的事發生,可以這樣:
eg:
1》 order = Order.find(params[:id], :conditions => ["user_id = ?", user_id])
2》 order = @user.orders.find(id)
3》 order = @user.orders.find(id).destroy
防御XSS攻擊:
攻擊者把自己編寫的javascript腳本放進網頁,來獲得他們想要的cookie,我們可以通過rails提供的h(string)輔助方法(實際上是html_escape()方法的別名)
生成rails項目的HTML文檔
rake doc:app
ActiveRecord::Errors.default_error_messages = hash
修改默認錯誤顯示信息
named_scope的使用:
named_scope :quanbu, :conditions => ["name=zcy"]
named_scope

Shili.quanbu.xianzhi(3)
顯示錯誤頁面:? 當指定的異常發生時,將顯示特定的頁面,這個最好放到application_controller中
rescue_from? 異常, :with => :action
eg:
rescue_from Exception, :with => :error
def error
? render :file => "novel/infos/error", :layout => "novel"
end
對于boolean類型的數據,應該省略前面的is_,ActiveRecord會自動加個?號,映射成actived? ,不是boolean型的數據也會也會擴展?
_form下的共享表單,區間的情況
1:map.namespace :doctor do |doctor|
??? doctor.resources :patients
end
["doctor", @patient ]
2:map.resources :doctor do |doctor|
??? doctor.resources :patients
end
[@doctor, @patient ]
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
