Ruby on rails开发从头来(四十七)- ActiveRecord基础(强大的find方法)


现在我们知道如何指定条件,现在我们来看看find方法支持的一些其他设置。

首先,理解find(:first,…)方法是非常重要的,该方法在同样的conditions设置下,和find(:all,…)方法生成同样的sql语句,不同之处仅在于只返回一条记录。在调用的时候,一种的参数为:first,另一种为:all。

find方法执行一个select from这样的sql语句,:all标记指定返回表中所有的记录,:first返回第一条记录。但是现在:first还不能保证你得到的就是表中的第一条记录,原因是什么?我们继续往下看。

:conditions参数指定了SQL语句的where部分,可以包含Sql语句或者包含可以替换的参数的名字,值,上一篇我们已经做了了解。

daves_orders = Order.find(:all, :conditions => "name = 'Dave'")

name = params[:name]

other_orders = Order.find(:all, :conditions => ["name = ?", name])

yet_more = Order.find(:all,

:conditions => ["name = :name and pay_type = :pay_type",

params])

上面的find方法并不能保证按照特定的顺序返回记录,除非指定查询的排序(order by)部分。:order参数就是用来指定SQL的排序条件的,下面的例子演示了查询名字为Dave的订单,并且按照pay_type,shipped_at字段进行降序排列。

orders = Order.find(:all,

:conditions => "name = 'Dave'",

:order => "pay_type, shipped_at DESC")

我们还可以设置:limit参数来限制返回的记录数,如果你使用:limit参数,或许还想指定排序条件,下面的例子返回10条记录,并且按照指定条件排序:

orders = Order.find(:all,

:conditions => "name = 'Dave'",

:order => "pay_type, shipped_at DESC",

:limit => 10)

参数:offset经常与:limit参数一同出现,用来指定从第一条记录起,返回指定的偏移量,下面代码演示了:offset参数的使用:

def Order.find_on_page(page_num, page_size)

find(:all,

:order => "id",

:limit => page_size,

:offset => page_num*page_size)

end

从上面的代码可以看到,这样使用find的场景就是分页显示数据,用pagesize指定每页的记录数,然后由pagenum*page_size指定从第几条开始提取数据。

参数:join用来指定主表和哪些表进行关联查询,:join参数指定的部分会插入到SQL中,下面的代码演示取得一个所有名为“Programing Ruby”的条目的列表:

LineItem.find(:all,

:conditions => "pr.title = 'Programming Ruby'",

:joins => "as li inner join products as pr on li.product_id = pr.id")

在后面的内容里,我们还会了解更多的进行表关联查询的方法。

现在,我们在来回头看看:all和:first参数,实际上在使用:first参数时,默认的带有参数:limit,只不过:limit参数的值为1。如果你要取得最后一条记录,只需要改变:order里的排序方向为降序。

find方法为我们构建了完整的Sql查询,而方法find_by_sql方法则允许我们对Sql有完整的控制,该方法只有一个参数,就是你想要使用的完整的sql语句,下面是示例代码:

orders = LineItem.find_by_sql("select line_items.* from line_items, orders " +

" where order_id = orders.id " +

" and orders.name = 'Dave Thomas' ")

现在有一个问题了,就是返回的Model对象中都包含有哪些属性呢?我们使用attributes( ), attribute_names( ), and attribute_present?( )方法来确定在Model对象中都包含有哪些属性,第一个返回一个hash,里面是键值对,第二个返回属性名的数组,第三个判断Model对象中是否含有某个属性,例如:

orders = Order.find_by_sql("select name, pay_type from orders")

first = orders[0]

p first.attributes

p first.attribute_names

p first.attribute_present?("address")

程序的结果:

{"name"=>"Dave Thomas", "pay_type"=>"check"}

["name", "pay_type"]

false

find_by_sql方法也可以用来创建包含有派生(derived)(注1)的Model对象,如果你使用了as XXX 这样的sql来给派生字段一个别名,这个别名会作为Model中的属性名,例如:

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}"

在find_by_sql方法中,我们一样可以使用占位符来给Sql语句传递参数,例如:

Order.find_by_sql(["select * from orders where amount > ?",

params[:amount]])

上一篇 下一篇

评论



分享

最新加入

最新评论

隋中缘: @嘉嘉tiffany 性感乳神。 查看原文 06月13日 16:16