Ruby on Rails數據庫操作

數據庫元被影射成對象
(object-relational mapping (ORM)層)
table<=>class
row<=>object
column<=>object attribute

class和table的命名對應關係實例
Order<=>orders
TaxAgency<=>tax_agencies
Person<=>people

複數形式關閉方法config/environment.rb:
ActiveRecord::Base.pluralize_table_names = false
自定義表格名稱方法:
class Sheep < ActiveRecord::Base
 set_table_name "sheep"
end

Ruyb數據類型和SQL數據類型對應關係表
int,integer<=>Fixnum
float,double,decimal,numeric<=>Float
interval,date<=>Date
datetime,time<=>Time
char,varchar,string,clob,blob,text<=>String
boolean<=>see text…

訪問屬性(數據庫列):
account[:balance] #=> 返回當前值
account[:balance] = 0.0 #=> 指定數值

修正數據庫列的取值範圍的方法:
class Account < ActiveRecord::Base
 def balance=(value)
  raise BalanceTooLow if value < MINIMUM_LEVEL
  self[:balance] = value
 end
end

訪問屬性(數據庫列)更方便的方法:
account.balance #=> 返回當前值
account.balance = 0.0 #=> 指定數值

以上方式得到的數據庫數據將是ruby按自身的數據類型格式化好的,如果要得到原始數據,可用以下形式代碼:
account.balance_before_type_cast #=> "123.4", 字符串
account.release_date_before_type_cast #=> "20050301"

是非屬性
在ruby中只有falsenil才被判斷為false

數據庫主鍵(Primary Keys)
Ruby on Rails默認以id為主鍵

自定義主鍵的方法:
class BadBook < ActiveRecord::Base
 set_primary_key "isbn"
end

數據創建,讀取,更新和刪除(CRUD:Create, Read, Update, Delete)

創建新數據

實例:
an_order = Order.new
an_order.name ="Dave Thomas"
an_order.save #在save()之前所有數據只存在內存中

用以下方式可以減少產生一個an_order變量:
Order.new do |o|
 o.name = "Dave Thomas"
 # . . .
 o.save
end

當數據來自HTML表單時,可以考慮用以下方式:
an_order = Order.new(
 :name =>"Dave Thomas",
#…
)
an_order.save

使用create()代換new()可直接保存到數據庫,省去an_order.save:
an_order = Order.create(
 :name => "Dave Thomas")

可以使用hash同時保存多組數據:
 orders = Order.create(
  [ { :name =>"Dave Thomas" },
   { :name =>"Andy Hunt" } ] )

new()或create()也可以直接接參數:
order = Order.create(params)

讀取數據
an_order = Order.find(27)
# 直接找出id = 27的數據,可以同時讀取多個object.
an_order = Order.find_by_id(27)
# 效果類似,但一次只能讀一個,在找不到符合的object時返回nil,而不是錯誤。
# 從一個表單讀取product id列表,然後計算這些商品的總價:
product_list = params[:product_ids]
total = 0.0
Product.find(product_list).each {|prd| total += prd.total}

帶條件的讀取:
pos = Order.find(:all,
:conditions => "name = ‘dave’ and pay_type = ‘po’")

不安全的表單參數傳遞讀取數據庫:
name = params[:name]
# 此方法有被SQL注入方式入侵的風險!!!
pos = Order.find(:all,
:conditions =>"name = ‘#{name}‘ and pay_type = ‘po’")
#注意上面單雙引號的使用及變量的傳遞方法

更安全的方法:
name = params[:name]
pos = Order.find(:all,
:conditions => ["name = ? and pay_type = 'po'", name])

你也可以這樣:
name = params[:name]
pay_type = params[:pay_type]
pos = Order.find(:all,
:conditions => ["name = :name and pay_type = :pay_type",
{:pay_type => pay_type, :name => name}])

終極簡化版:
pos = Order.find(:all,
:conditions => ["name = :name and pay_type = :pay_type", params])

排序和查找第3(?)至13(?)列的方法:
orders = Order.find(:all,
 :conditions =>"name = ‘Dave’",
 :order =>"pay_type, shipped_at DESC",
 :limit => 10
 :offset => 2)

聯合數據表的查找方法(一般用不上):
LineItem.find(:all,
:conditions => "pr.title = ‘Programming Ruby’",
:joins =>"as li inner join products as pr on li.product_id = pr.id")

查找有序一列的方法:
order = Order.find( :first,
 :conditions =>"name = ‘Dave Thomas’",
 :order => "id DESC")

直接使用sql語句的查詢方法:
items = LineItem.find_by_sql("select *, quantity*unit_price as total_price,products.title as title from line_items, products where line_items.product_id = products.id ")
li = items[0]
puts "#{li.title}: #{li.quantity}x#{li.unit_price} => #{li.total_price}"
你可以使用"as".

在這裡你也可以傳遞參數:
Order.find_by_sql(["select * from orders where amount > ?",
params[:amount]])

計算行數
c1 = Order.count
c2 = Order.count(["name = ?", "Dave Thomas"])
c3 = LineItem.count_by_sql("select count(*) from line_items, orders  where line_items.order_id = orders.id and orders.name = ‘Dave Thomas’ ")
puts "Dave在#{c2}個定單里一共定了#{c3} 件商品 (目前定單總數:#{c1})"

動態查詢
order = Order.find_by_name("Dave Thomas")#只查一列
orders = Order.find_all_by_name("Dave Thomas")
order = Order.find_all_by_email(params['email'])

可同時查多個條件,如:
user = User.find_by_name_and_password(name, pw)

重載數據庫
stock = Market.find_by_ticker("RUBY")
loop do
 puts "Price = #{stock.price}"
 sleep 60
 stock.reload
end

更新數據
使用save()
order = Order.find(123)
order.name = "Fred"
order.save

orders = Order.find_by_sql("select id, name, pay_type from orders where id=123")
first = orders[0]
first.name ="Wilma"
first.save

使用update_attribute()
order = Order.find(123)
order.update_attribute(:name,"Barney")
order = Order.find(321)
order.update_attributes(:name => "Barney",
:email =>"barney@bedrock.com")

使用更快捷的update()
order = Order.update(12, :name => "Barney", :email => "barney@bedrock.com")

使用update_all()
result = Product.update_all("price = 1.1*price", "title like ‘%Java%‘")

save()和save!()
save()失敗時返回nil
if order.save
 # 成功
else
 # 保存失敗則…
end

save!()失敗時出錯
begin
 order.save!
rescue RecordInvalid => error
 # 保存失敗RecordInvalid exception
end

數據鎖(防止數據保存撞車)
加段:lock_version int default 0,

刪除數據
delete()刪除
Order.delete(123)
User.delete([2,3,4,5])
Product.delete_all(["price > ?", @expensive_price])

destroy()凍結(在model層面)
order = Order.find_by_name("Dave")
order.destroy
# … order將被凍結

數據庫關係(相關鍵)參看:Ruby on Rails數據表格關係

此條目發表在 Ruby on Rails 分類目錄。將固定鏈接加入收藏夾。

發表評論