Rails 数据库操作

数据库元被影射成对象
(object-relational mapping (ORM)层)

Ruby代码
  1. table<=>class  
  2. row<=>object   
  3. column<=>object attribute  
table<=>class
row<=>object
column<=>object attribute



class和table的命名对应关系实例:

Ruby代码
  1. Order<=>orders   
  2. TaxAgency<=>tax_agencies   
  3. Person<=>people  
Order<=>orders
TaxAgency<=>tax_agencies
Person<=>people

 

Ruby代码
  1. #复数形式关闭方法config/environment.rb:   
  2. ActiveRecord::Base.pluralize_table_names = false  
  3. #自定义表格名称方法:   
  4. class Sheep < ActiveRecord::Base   
  5. set_table_name "sheep"  
  6. end  
#复数形式关闭方法config/environment.rb:
ActiveRecord::Base.pluralize_table_names = false
#自定义表格名称方法:
class Sheep < ActiveRecord::Base
set_table_name "sheep"
end



Ruyb数据类型和SQL数据类型对应关系表:

Ruby代码
  1. int,integer<=>Fixnum  
  2. float,double,decimal,numeric<=>Float   
  3. interval,date<=>Date   
  4. datetime,time<=>Time  
  5. char,varchar,string,clob,blob,text<=>String  
  6. boolean<=>see text...  
int,integer<=>Fixnum
float,double,decimal,numeric<=>Float
interval,date<=>Date
datetime,time<=>Time
char,varchar,string,clob,blob,text<=>String
boolean<=>see text...



访问属性(数据库列):

Ruby代码
  1. account[:balance#=> 返回当前值   
  2. account[:balance] = 0.0 #=> 指定数值  
account[:balance] #=> 返回当前值
account[:balance] = 0.0 #=> 指定数值


Ruby代码
  1. #修正数据库列的取值范围的方法:   
  2. class Account < ActiveRecord::Base   
  3. def balance=(value)   
  4.    raise BalanceTooLow if value < MINIMUM_LEVEL   
  5.    self[:balance] = value   
  6. end  
  7. end  
#修正数据库列的取值范围的方法:
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中只有false或nil才被判断为false
通常用以下代码判断:

Ruby代码
  1. user = Users.find_by_name("Dave")   
  2. if user.superuser?   
  3. grant_privileges   
  4. end  
user = Users.find_by_name("Dave")
if user.superuser?
grant_privileges
end


superuser?将以下结果判断为false:
1.数字0
2.字符"0", "f", "false", 或""(空字符)
3.nil
4.常量false

自定义判断原则的方法:

Ruby代码
  1. class User < ActiveRecord::Base   
  2. def superuser?   
  3.    self.superuser == 'J'  
  4. end  
  5. # . . .   
  6. end  
class User < ActiveRecord::Base
def superuser?
   self.superuser == 'J'
end
# . . .
end



数据库主键(Primary Keys)
Ruby on Rails默认以id为主键

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

数据创建,读取,更新和删除(CRUD:Create, Read, Update, Delete)

创建新数据

实例:

Ruby代码
  1. an_order = Order.new  
  2. an_order.name ="Dave Thomas"  
  3. an_order.email = "dave@pragprog.com"  
  4. an_order.address = "123 Main St"  
  5. an_order.pay_type = "check"  
  6. an_order.save #在save()之前所有数据只存在内存中  
an_order = Order.new
an_order.name ="Dave Thomas"
an_order.email = "dave@pragprog.com"
an_order.address = "123 Main St"
an_order.pay_type = "check"
an_order.save #在save()之前所有数据只存在内存中



用以下方式可以减少产生一个an_order变量:

Ruby代码
  1. Order.new do |o|   
  2. o.name = "Dave Thomas"  
  3. # . . .   
  4. o.save   
  5. end  
Order.new do |o|
o.name = "Dave Thomas"
# . . .
o.save
end



当数据来自HTML表单时,可以考虑用以下方式:

Ruby代码
  1. an_order = Order.new(   
  2. :name =>"Dave Thomas",   
  3. :email =>"dave@pragprog.com",   
  4. :address => "123 Main St",   
  5. :pay_type =>"check")   
  6. an_order.save  
an_order = Order.new(
:name =>"Dave Thomas",
:email =>"dave@pragprog.com",
:address => "123 Main St",
:pay_type =>"check")
an_order.save



使用create()代换new()可直接保存到数据库,省去an_order.save:

Ruby代码
  1. an_order = Order.create(   
  2. :name => "Dave Thomas",   
  3. :email =>"dave@pragprog.com",   
  4. :address =>"123 Main St",   
  5. :pay_type => "check")  
an_order = Order.create(
:name => "Dave Thomas",
:email =>"dave@pragprog.com",
:address =>"123 Main St",
:pay_type => "check")



可以使用hash同时保存多组数据:

Ruby代码
  1. orders = Order.create(   
  2.    [ { :name =>"Dave Thomas",   
  3.      :email => "dave@pragprog.com",   
  4.      :address =>"123 Main St",   
  5.      :pay_type =>"check"  
  6.     },   
  7.     { :name =>"Andy Hunt",   
  8.      :email =>"andy@pragprog.com",   
  9.      :address =>"456 Gentle Drive",   
  10.      :pay_type => "po"  
  11.     } ] )  
orders = Order.create(
   [ { :name =>"Dave Thomas",
     :email => "dave@pragprog.com",
     :address =>"123 Main St",
     :pay_type =>"check"
    },
    { :name =>"Andy Hunt",
     :email =>"andy@pragprog.com",
     :address =>"456 Gentle Drive",
     :pay_type => "po"
    } ] )



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

读取数据

Ruby代码
  1. an_order = Order.find(27) # 直接找出id = 27的数据   
  2. # 从一个表单读取product id列表,然后计算这些商品的总价:   
  3. product_list = params[:product_ids]   
  4. total = 0.0   
  5. Product.find(product_list).each {|prd| total += prd.total}  
an_order = Order.find(27) # 直接找出id = 27的数据
# 从一个表单读取product id列表,然后计算这些商品的总价:
product_list = params[:product_ids]
total = 0.0
Product.find(product_list).each {|prd| total += prd.total}


Ruby代码
  1. 带条件的读取:   
  2. pos = Order.find(:all,   
  3. :conditions => "name = 'dave' and pay_type = 'po'")  
带条件的读取:
pos = Order.find(:all,
:conditions => "name = 'dave' and pay_type = 'po'")



不安全的表单参数传递读取数据库:

Ruby代码
  1. name = params[:name]   
  2. # 此方法有被SQL注入方式入侵的风险!!!   
  3. pos = Order.find(:all,   
  4. :conditions =>"name = '#{name}' and pay_type = 'po'")   
  5. #注意上面单双引号的使用及变量的传递方法  
name = params[:name]
# 此方法有被SQL注入方式入侵的风险!!!
pos = Order.find(:all,
:conditions =>"name = '#{name}' and pay_type = 'po'")
#注意上面单双引号的使用及变量的传递方法


更安全的方法:

Ruby代码
  1. name = params[:name]   
  2. pos = Order.find(:all,   
  3. :conditions => ["name = ? and pay_type = 'po'", name])  
name = params[:name]
pos = Order.find(:all,
:conditions => ["name = ? and pay_type = 'po'", name])



你也可以这样:

Ruby代码
  1. name = params[:name]   
  2. pay_type = params[:pay_type]   
  3. pos = Order.find(:all,   
  4. :conditions => ["name = :name and pay_type = :pay_type",   
  5. {:pay_type => pay_type, :name => 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}])



终极简化版:

Ruby代码
  1. pos = Order.find(:all,   
  2. :conditions => ["name = :name and pay_type = :pay_type", params])  
pos = Order.find(:all,
:conditions => ["name = :name and pay_type = :pay_type", params])



排序和查找第3(?)至13(?)列的方法:

Ruby代码
  1. orders = Order.find(:all,   
  2. :conditions =>"name = 'Dave'",   
  3. :order =>"pay_type, shipped_at DESC",   
  4. :limit => 10   
  5. :offset => 2)  
orders = Order.find(:all,
:conditions =>"name = 'Dave'",
:order =>"pay_type, shipped_at DESC",
:limit => 10
:offset => 2)



联合数据表的查找方法(一般用不上):

Ruby代码
  1. LineItem.find(:all,   
  2. :conditions => "pr.title = 'Programming Ruby'",   
  3. :joins =>"as li inner join products as pr on li.product_id = pr.id")  
LineItem.find(:all,
:conditions => "pr.title = 'Programming Ruby'",
:joins =>"as li inner join products as pr on li.product_id = pr.id")


查找有序一列的方法:

Ruby代码
  1. order = Order.find( :first,   
  2. :conditions =>"name = 'Dave Thomas'",   
  3. :order => "id DESC")  
order = Order.find( :first,
:conditions =>"name = 'Dave Thomas'",
:order => "id DESC")



直接使用sql语句的查询方法:

Ruby代码
  1. 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 ")   
  2. li = items[0]   
  3. puts "#{li.title}: #{li.quantity}x#{li.unit_price} => #{li.total_price}"  
  4. #你可以使用"as".  
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".



在这里你也可以传递参数:

Ruby代码
  1. Order.find_by_sql(["select * from orders where amount > ?",   
  2. params[:amount]])  
Order.find_by_sql(["select * from orders where amount > ?",
params[:amount]])



计算行数

Ruby代码
  1. c1 = Order.count   
  2. c2 = Order.count(["name = ?""Dave Thomas"])   
  3. c3 = LineItem.count_by_sql("select count(*) from line_items, orders   where line_items.order_id = orders.id and orders.name = 'Dave Thomas' ")   
  4. puts "Dave在#{c2}个定单里一共定了#{c3} 件商品 (目前定单总数:#{c1})"  
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})"



动态查询

Ruby代码
  1. order = Order.find_by_name("Dave Thomas")#只查一列   
  2. orders = Order.find_all_by_name("Dave Thomas")   
  3. order = Order.find_all_by_email(params['email'])  
order = Order.find_by_name("Dave Thomas")#只查一列
orders = Order.find_all_by_name("Dave Thomas")
order = Order.find_all_by_email(params['email'])



可同时查多个条件,如:

Ruby代码
  1. user = User.find_by_name_and_password(name, pw)  
user = User.find_by_name_and_password(name, pw)



重载数据库

Ruby代码
  1. stock = Market.find_by_ticker("RUBY")   
  2. loop do  
  3. puts "Price = #{stock.price}"  
  4. sleep 60   
  5. stock.reload   
  6. end  
stock = Market.find_by_ticker("RUBY")
loop do
puts "Price = #{stock.price}"
sleep 60
stock.reload
end



更新数据
使用save()

Ruby代码
  1. order = Order.find(123)   
  2. order.name = "Fred"  
  3. order.save   
  4.   
  5. orders = Order.find_by_sql("select id, name, pay_type from orders where id=123")   
  6. first = orders[0]   
  7. first.name ="Wilma"  
  8. first.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()

Ruby代码
  1. order = Order.find(123)   
  2. order.update_attribute(:name,"Barney")   
  3. order = Order.find(321)   
  4. order.update_attributes(:name => "Barney",   
  5. :email =>"barney@bedrock.com")  
order = Order.find(123)
order.update_attribute(:name,"Barney")
order = Order.find(321)
order.update_attributes(:name => "Barney",
:email =>"barney@bedrock.com")



使用更快捷的update()

Ruby代码
  1. order = Order.update(12, :name => "Barney":email => "barney@bedrock.com")  
order = Order.update(12, :name => "Barney", :email => "barney@bedrock.com")



使用update_all()

Ruby代码
  1. result = Product.update_all("price = 1.1*price""title like '%ruby%'")  
result = Product.update_all("price = 1.1*price", "title like '%ruby%'")


Ruby代码
  1. save()和save!()   
  2. save()   
  3. if order.save   
  4. # 成功   
  5. else  
  6. # 保存失败则...   
  7. end  
save()和save!()
save()
if order.save
# 成功
else
# 保存失败则...
end


Ruby代码
  1. save!()   
  2. begin  
  3. order.save!   
  4. rescue RecordInvalid => error   
  5. # 保存失败RecordInvalid exception   
  6. end  
save!()
begin
order.save!
rescue RecordInvalid => error
# 保存失败RecordInvalid exception
end



数据锁(防止数据保存撞车)
加段:lock_version int default 0,


删除数据

Ruby代码
  1. delete()删除   
  2. Order.delete(123)   
  3. User.delete([2,3,4,5])   
  4. Product.delete_all(["price > ?"@expensive_price])  
delete()删除
Order.delete(123)
User.delete([2,3,4,5])
Product.delete_all(["price > ?", @expensive_price])



destroy()冻结(在model层面)

Ruby代码
  1. order = Order.find_by_name("Dave")   
  2. order.destroy   
  3. # ... order将被冻结  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值