程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Rails開發細節(二)CRUD

Rails開發細節(二)CRUD

編輯:關於JAVA

Create & Save

創建 & 保存

order = Order.new
order.name = "virusswb"
order.email = "[email protected]"
order.save

調用save方法之後就可以保存到數據庫了。

還可以用block來創建並保存。

Order.new do |order| 
  order.name = "virusswb"
  order.email = "[email protected]"
  order.save 
end

還可以使用hash的方式創建並保存。

order = Order.new( 
  :name => "virus", 
  :email => "[email protected]"
) 
order.save

默認id主鍵不用賦值,是integer的自增列。

上面的方法都需要調用save方法才 能保存到數據庫,用create方法可以合二為一,創建同時保存到數據庫。

order = Order.create( 
  :name => "virus", 
  :email => "[email protected]"
)

還可以一次保存多個,只要給create傳遞一個數組就可以實現。

orders = 

Order.create( 
  [{ :name => "virus1", 
     :email => "[email protected]"
   }, 
   { :name => "swb2", 
     :email => "[email protected]"
   }] 
)

返回也是一個數組。

從form放入參數中直接創建一個model對象。

@order = Order.new(params[:order])

Order.find(1)可以用來獲取id=1的model,但是如果數據表中不存在 id=1的model,就會拋出RecordNotFound異常。

如果使用Order.where(:id => 1).first,是告訴數 據庫“我需要id=1的記錄”,如果不存在這樣的記錄,不會拋出異常,返回的是nil。

Reading Existing Rows

讀取

an_order = Order.find(27)

返回一條記錄,如果沒有,會拋出 RecordNotFound異常。

product_list = params[:product_ids]

total = Product.find (product_list).sum(&:price)

給find傳入array,可以實現多條記錄的查詢,但是如果其中一個 id不存在的話,還是會拋出RecordNotFound異常 。

Dynamic Finders

動態查詢

有時候 我們會針對model的一列進行查詢,在rails中不用寫sql就可以實現。

order = Order.find_by_name ("virus")

orders = Order.find_all_by_name("virus")

orders = Order.find_all_by_email(params['email'])

 

order = Order.find_by_name ("virus")

order = Order.where(:name => "virus").first

效果是一樣的。

還有find_all_by_xxx和find_last_by_xxx這樣的查詢。

如果在find_by_方法 後面加上一個!,就會在找不到記錄的情況下拋出RecordNotFound異常。

order = Order.find_by_name!("virus")

還可以多列查詢。

order = Order.find_by_name_and_password(name,pw)

order = Order.where(:name => name, :password => pw).first

是一樣的效果。

有些情況下,你想要確保有model,如果在數據 庫中不存在,就創建一個,動態的finders就可以實現這個需求。find_or_initialize_by_或者 find_or_create_by_可以實現沒有滿足條件的記錄,就返回nil,就會創建或者直接保存記錄。

cart = Cart.find_or_initialize_by_user_id(user.id)

cart.items << new_item

cart.save

SQL and ActiveRecord

在AcriveRecord中使用SQL

用model的where方法可以實現sql語 句的where子句。

pos = Order.where("name = 'virus' and emal = '[email protected]'")  

接收外部傳過來的name的值。

name = params[:name]

pos = Order.where("name = '#{name}' and email = '[email protected]'")

上面拼接sql語句的方式,會受到sql注入攻擊。

安全的方式是讓ActiveRecord來處理,參數化 。

name = params[:name]

pos = Order.where(["name = ? and email ='sd'", name])

 

name = params[:name]

email = params[:email]

pos = Order.where("name = :name and email = :email",  

               { :name => name, :email => email})
 

因為params已經 是hash了,可以簡潔一些。

 

pos = Order.where("name = :name and email = :email",  

               params[:order])

還可以更 簡潔一些。

pos = Order.where(params[:order])

要小心上面的寫法,它使用了所有的參數 ,通過下面的寫法,你可以指定使用哪些參數。

pos = Order.where( :name => params[:name], :email => params[:email])

Using like Clauses

使用like子句

User.where ("name like ?", params[:name] + "%")

Subsetting the Recods Returned

返回部分數據

order排序

orders = Order.where(:name => params [:name])

             .order("name, email desc")

limit限制返回的條數

orders = Order.where(:name => params[:name])

             .order("name, email desc")

.limit(10)

offset跳過行

offset相當於mysql中的skip。

def 

Order.find_on_page(page_num, page_size)
orders = Order.where(:name => params[:name]) 
               .order("name, email desc")
.limit(page_size)
.offset(page_num*page_size)
end

select選擇列

默認選擇所有的列,可以通過select來查詢需要的列。

orders = 

Order.where(:name => params[:name]) 
              .order("name, email desc")
.select("name, email")

joins連接

LineItem.select('li.quantity') 
.where("pr.title = 'programming in ruby'") 
.joins("as li inner join products pr on li.product_id=pr.id")

readonly只讀

使用 readonly方法獲取的記錄,不能再保存回數據庫。

如果使用joins或者是select方法,返回的對象自動 標記為readonly。

group分組

會產生group by子句。

summary = LineItem.select (select = > "sku, sum(amount) as amount")

.group("sku")

lock鎖

lock方法的參數是一個字符串,告訴數據庫使用指定類型的鎖。

在mysql中共享鎖返回最新的 數據行,並且確保沒有人可以在鎖期間修改這條記錄。

Account.transaction do
  ac = Account.where(:id => id).lock("LOCK IN SHARE MODE").first 
  ac.balance -= amount if ac.balance > amount 
  ac.save 
end

Getting Column Statistics

聚合統計

average = Order.average(:amount) 
max = Order.maximun(:amount) 
min = Order.minimun(:amount) 
total = Order.sum(:amount) 
number = Order.count

上面的這些聚合函數都是數據庫無關的。

也可以聯合其他方法一起使 用。

Order.where("amount > 20").minimun(:amount)

通常情況,這些聚合函 數返回的是一個值。如果包含group方法,返回的就是每一組的聚合結果,也就是返回一系列值。

result = Order.maximun(:amount).group(:state)

puts result #=> [["TX", 123456], ["NX", 3456]]

Scopes

范圍查詢

class Order < 

ActiveRecord::Base 
  scope :last_n_days, lambda do |days| 
    where("updated < ?", days) 
  end 
end 
     
orders= Order.last_n_days(7) 
     
class Order < ActiveRecord::Base 
  scope :checks, where(:pay_type => :check) 
end 
     
orders = Order.checks.last_n_days(7) 
     
in_house = Order.where('email like "%@pragprog.com"') 
     
in_house.checks.last_n_days(7)

Writing Our Own SQL

執行查詢SQL

orders = LineItem.find_by_sql("select line_items.* from line_items, orders where order_id = orders.id and orders.name = 'virus'"

orders = Order.find_by_sql("select 

name, pay_type from orders") 
     
first = orders[0] 
p first.attributes  #=>{"name" => "shi", "pay_type" => "check"} 
p first.attribute_names #=>["name", "pay_type"] 
p first.attribute_present?("address") #=>false

Reloading Data

重新加載數據

我們的應用會被多個用戶訪問,有的時候,之前取出來的數據已經被其他用戶修改,這時候你又需要 最新的數據,可以調用model的reload方法來實現。

loop do
  puts "Price = #{stock.price}"
  sleep 60 
     
  stock.reload 
end

Updating Existing Rows

更新數據

調用model的save方法就可以實現更新,通過 id來匹配數據,如果存在數據,就是更新,如果不存在數據,就插入一條。

order = Order.find

(10) 
order.name = "swb"
order.save 
     
orders = Order.find_by_sql("select id, name, email from orders where id = 12") 
first = orders[0] 
first.name = "newname"
first.save 
     
order = Order.find(12) 
order.update_attribute(:name, "newname") 
     
order = Order.find(12) 
order.update_attributes(:name => "newname", :email => "newmail") 
     
def save_after_edit 
  order = Order.find(params[:id]) 
  if order.update_attributes(params[:order]) 
    redirect_to :action => :index 
  else
    render :action => :edit 
  end 
end 
     
order = Order.update(12, :name => "newname", :email => "newmail") 
     
result = Order.update_all("price = 1.1*price", "title like '%java%'")

save, save!, create, create!

save,保存成功返回true,否則返回nil。

save!,保存成功返回true,否則拋出 異常。

create,無論保存成功與否,都會返回model對象。你需要通過檢查validation errros來確定保存 是否成功。

create!,保存成功返回true,否則拋出異常。
 

if order.save 
  # all ok 
else
  # validation fail 
end 
     
begin 
  order.save! 
rescue RecordInvalid => error 
  # validation fail 
end

Deleting Rows

刪除數據

類級別的delete方法

Order.delete(10)

User.delete([2,3,4,5])

Product.delete_all(["price > ?", @expensize_price])

delete方法通過id或者id集合刪除數據,delete_all通過條件刪除數據,返回值是受影響的行數,沒 有符合條件的數據也不會拋出異常。

對象級別的destroy方法

order = Order.find(10)

order.destroy

調用對象的destroy方法之後,就會鎖定對象,防止對他進行修改。

Order.destroy_all(["price > ?", @expensize_price])

delete方法會忽略驗 證功能,destroy方法會確保它們被執行。通常來說,如果你想要確保你的數據符合業務規則,最好使用 destroy方法。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved