Rails开发细节《二》CRUD

简介:

Create & Save

创建 & 保存

 
  1. order = Order.new 
  2. order.name = "virusswb" 
  3. order.email = "asdf@exmaple.com" 
  4. order.save 

调用save方法之后就可以保存到数据库了。

还可以用block来创建并保存。

 
  1. Order.new do |order| 
  2.   order.name = "virusswb" 
  3.   order.email = "asdf@example.com" 
  4.   order.save 
  5. end 

还可以使用hash的方式创建并保存。

 

 
  1. order = Order.new
  2.   :name => "virus"
  3.   :email => "adf@example.com" 
  4. order.save 

默认id主键不用赋值,是integer的自增列。

上面的方法都需要调用save方法才能保存到数据库,用create方法可以合二为一,创建同时保存到数据库。

 

 
  1. order = Order.create( 
  2.   :name => "virus"
  3.   :email => "adf@exmaple.com" 

还可以一次保存多个,只要给create传递一个数组就可以实现。

 

 
  1. orders = Order.create( 
  2.   [{ :name => "virus1", 
  3.      :email => "111@123.com" 
  4.    }, 
  5.    { :name => "swb2", 
  6.      :email => "222@123.com" 
  7.    }] 

返回也是一个数组。

从form放入参数中直接创建一个model对象。

 

 
  1. @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

读取

 

 
  1. an_order = Order.find(27) 

返回一条记录,如果没有,会抛出RecordNotFound异常。

 

 
  1. product_list = params[:product_ids] 
  2. total = Product.find(product_list).sum(&:price) 

给find传入array,可以实现多条记录的查询,但是如果其中一个id不存在的话,还是会抛出RecordNotFound异常 。

Dynamic Finders

动态查询

有时候我们会针对model的一列进行查询,在rails中不用写sql就可以实现。

 

 
  1. order = Order.find_by_name("virus"
  2. orders = Order.find_all_by_name("virus"
  3. orders = Order.find_all_by_email(params['email']) 

 

 
  1. order = Order.find_by_name("virus"

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

效果是一样的。

还有find_all_by_xxx和find_last_by_xxx这样的查询。

如果在find_by_方法后面加上一个!,就会在找不到记录的情况下抛出RecordNotFound异常。

 

 
  1. order = Order.find_by_name!("virus"

还可以多列查询。

 

 
  1. order = Order.find_by_name_and_password(name,pw) 

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

是一样的效果。

有些情况下,你想要确保有model,如果在数据库中不存在,就创建一个,动态的finders就可以实现这个需求。find_or_initialize_by_或者find_or_create_by_可以实现没有满足条件的记录,就返回nil,就会创建或者直接保存记录。

 

 
  1. cart = Cart.find_or_initialize_by_user_id(user.id) 
  2. cart.items << new_item 
  3. cart.save 

SQL and ActiveRecord

在AcriveRecord中使用SQL

用model的where方法可以实现sql语句的where子句。

 
  1. pos = Order.where("name = 'virus' and emal = 'sf@123.com'"

 

接收外部传过来的name的值。

 
  1. name = params[:name] 
  2. pos = Order.where("name = '#{name}' and email = '123@123.com'") 

上面拼接sql语句的方式,会受到sql注入攻击。

安全的方式是让ActiveRecord来处理,参数化。

 

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

 

 
  1. name = params[:name
  2. email = params[:email
  3. pos = Order.where("name = :name and email = :email",  
  4.                 { :name => name, :email => email}) 

 

因为params已经是hash了,可以简洁一些。

 

 
  1.  
  2. pos = Order.where("name = :name and email = :email",  
  3.                 params[:order]

还可以更简洁一些。

 

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

要小心上面的写法,它使用了所有的参数,通过下面的写法,你可以指定使用哪些参数。

 

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

Using like Clauses

使用like子句

 

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

Subsetting the Recods Returned

返回部分数据

order排序

 

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

limit限制返回的条数

 

 
 
  1. orders = Order.where(:name => params[:name]) 
  2.               .order("name, email desc")
  3. .limit(10)

offset跳过行

offset相当于mysql中的skip。

 
  1. def Order.find_on_page(page_num, page_size)
  2. orders = Order.where(:name => params[:name]) 
  3.                .order("name, email desc")
  4. .limit(page_size)
  5. .offset(page_num*page_size)
  6. end

select选择列

默认选择所有的列,可以通过select来查询需要的列。

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

joins连接

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

readonly只读

使用readonly方法获取的记录,不能再保存回数据库。

如果使用joins或者是select方法,返回的对象自动标记为readonly。

group分组

会产生group by子句。

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

lock锁

lock方法的参数是一个字符串,告诉数据库使用指定类型的锁。

在mysql中共享锁返回最新的数据行,并且确保没有人可以在锁期间修改这条记录。

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

 

Getting Column Statistics

聚合统计

 
  1. average = Order.average(:amount
  2. max = Order.maximun(:amount
  3. min = Order.minimun(:amount
  4. total = Order.sum(:amount
  5. number = Order.count 

上面的这些聚合函数都是数据库无关的。

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

 

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

通常情况,这些聚合函数返回的是一个值。如果包含group方法,返回的就是每一组的聚合结果,也就是返回一系列值。

 

 
  1. result = Order.maximun(:amount).group(:state
  2. puts result #=> [["TX", 123456], ["NX", 3456]] 

Scopes

范围查询

 
  1. class Order < ActiveRecord::Base 
  2.   scope :last_n_days, lambda do |days| 
  3.     where("updated < ?", days) 
  4.   end 
  5. end 
  6.  
  7. orders= Order.last_n_days(7) 
  8.  
  9. class Order < ActiveRecord::Base 
  10.   scope :checks, where(:pay_type => :check
  11. end 
  12.  
  13. orders = Order.checks.last_n_days(7) 
  14.  
  15. in_house = Order.where('email like "%@pragprog.com"'
  16.  
  17. in_house.checks.last_n_days(7) 

Writing Our Own SQL

执行查询SQL

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

 

 

 
  1. orders = Order.find_by_sql("select name, pay_type from orders"
  2.  
  3. first = orders[0] 
  4. p first.attributes  #=>{"name" => "shi", "pay_type" => "check"} 
  5. p first.attribute_names #=>["name", "pay_type"] 
  6. p first.attribute_present?("address"#=>false 

Reloading Data 

重新加载数据

我们的应用会被多个用户访问,有的时候,之前取出来的数据已经被其他用户修改,这时候你又需要最新的数据,可以调用model的reload方法来实现。

 

 
  1. loop do 
  2.   puts "Price = #{stock.price}" 
  3.   sleep 60 
  4.  
  5.   stock.reload 
  6. end 

Updating Existing Rows

更新数据

调用model的save方法就可以实现更新,通过id来匹配数据,如果存在数据,就是更新,如果不存在数据,就插入一条。

 
  1. order = Order.find(10) 
  2. order.name = "swb" 
  3. order.save 
  4.  
  5. orders = Order.find_by_sql("select id, name, email from orders where id = 12"
  6. first = orders[0] 
  7. first.name = "newname" 
  8. first.save 
  9.  
  10. order = Order.find(12) 
  11. order.update_attribute(:name"newname"
  12.  
  13. order = Order.find(12) 
  14. order.update_attributes(:name => "newname":email => "newmail"
  15.  
  16. def save_after_edit 
  17.   order = Order.find(params[:id]) 
  18.   if order.update_attributes(params[:order]) 
  19.     redirect_to :action => :index 
  20.   else 
  21.     render :action => :edit 
  22.   end 
  23. end 
  24.  
  25. order = Order.update(12, :name => "newname":email => "newmail"
  26.  
  27. 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,否则抛出异常。
 
  1. if order.save 
  2.   # all ok 
  3. else 
  4.   # validation fail 
  5. end 
  6.  
  7. begin 
  8.   order.save! 
  9. rescue RecordInvalid => error 
  10.   # validation fail 
  11. end 

Deleting Rows

删除数据

类级别的delete方法

 

 
  1. Order.delete(10) 
  2. User.delete([2,3,4,5]) 
  3. Product.delete_all(["price > ?"@expensize_price]) 

delete方法通过id或者id集合删除数据,delete_all通过条件删除数据,返回值是受影响的行数,没有符合条件的数据也不会抛出异常。

对象级别的destroy方法

 

 
  1. order = Order.find(10) 
  2. order.destroy 

调用对象的destroy方法之后,就会锁定对象,防止对他进行修改。

 

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

delete方法会忽略验证功能,destroy方法会确保它们被执行。通常来说,如果你想要确保你的数据符合业务规则,最好使用destroy方法。




本文转自 virusswb 51CTO博客,原文链接:http://blog.51cto.com/virusswb/1016292,如需转载请自行联系原作者

目录
相关文章
|
30天前
|
前端开发 Java 数据库连接
Java后端开发-使用springboot进行Mybatis连接数据库步骤
本文介绍了使用Java和IDEA进行数据库操作的详细步骤,涵盖从数据库准备到测试类编写及运行的全过程。主要内容包括: 1. **数据库准备**:创建数据库和表。 2. **查询数据库**:验证数据库是否可用。 3. **IDEA代码配置**:构建实体类并配置数据库连接。 4. **测试类编写**:编写并运行测试类以确保一切正常。
56 2
|
2月前
|
存储 前端开发 关系型数据库
鸿蒙开发:实现键值数据库存储
对于数据量比较的小的,我们直接选择轻量级的用户首选项方式即可,而对于数据量比较大的情况下,直接可以使用数据库,而对于相对来说,比较大的数据,我们就可以使用键值型数据库方式
104 2
|
2月前
|
SQL 关系型数据库 API
HarmonyOs开发:关系型数据库封装之增删改查
每个方法都预留了多种调用方式,比如使用callback异步回调或者使用Promise异步回调,亦或者同步执行,大家在使用的过程中,可以根据自身业务需要进行选择性调用,也分别暴露了成功和失败的方法,可以针对性的判断在执行的过程中是否执行成功。
112 13
|
2月前
|
存储 JSON 测试技术
【HarmonyOS Next开发】云开发-云数据库(二)
实现了云侧和端侧的云数据库创建、更新、修改等操作。这篇文章实现调用云函数对云数据库进行增删改查。
65 9
【HarmonyOS Next开发】云开发-云数据库(二)
|
3月前
|
存储 缓存 NoSQL
2款使用.NET开发的数据库系统
2款使用.NET开发的数据库系统
|
3月前
|
存储 SQL API
探索后端开发:构建高效API与数据库交互
【10月更文挑战第36天】在数字化时代,后端开发是连接用户界面和数据存储的桥梁。本文深入探讨如何设计高效的API以及如何实现API与数据库之间的无缝交互,确保数据的一致性和高性能。我们将从基础概念出发,逐步深入到实战技巧,为读者提供一个清晰的后端开发路线图。
|
3月前
|
存储 SQL 数据库
深入浅出后端开发之数据库优化实战
【10月更文挑战第35天】在软件开发的世界里,数据库性能直接关系到应用的响应速度和用户体验。本文将带你了解如何通过合理的索引设计、查询优化以及恰当的数据存储策略来提升数据库性能。我们将一起探索这些技巧背后的原理,并通过实际案例感受优化带来的显著效果。
73 4
|
3月前
|
存储 Java 关系型数据库
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践,包括连接创建、分配、复用和释放等操作,并通过电商应用实例展示了如何选择合适的连接池库(如HikariCP)和配置参数,实现高效、稳定的数据库连接管理。
92 2
|
3月前
|
监控 Java 数据库连接
在Java开发中,数据库连接管理是关键问题之一
在Java开发中,数据库连接管理是关键问题之一。本文介绍了连接池技术如何通过预创建和管理数据库连接,提高数据库操作的性能和稳定性,减少资源消耗,并简化连接管理。通过示例代码展示了HikariCP连接池的实际应用。
33 1
|
4月前
|
SQL JavaScript 关系型数据库
node博客小项目:接口开发、连接mysql数据库
【10月更文挑战第14天】node博客小项目:接口开发、连接mysql数据库

热门文章

最新文章