我的Rails应用程序开始需要复杂的查询.我应该开始使用原始SQL查询吗? Rails社区的趋势是什么?
更新:
我现在没有书面查询,我想在开始之前提出这个问题.但这是我想要做的一个例子:
我有有类别的书.我想说-
Give me all books that were: -created_at (added to store) between date1 and date2 -updated_at before date3 -joined with books that exist in shopping carts right now
我还没有编写查询,但我认为rails版本将是这样的:
books_to_consider = Book.find(:all,:conditions => "created_at <= '#{date2}' AND created_at >= '#{date1}' AND updated_at <= '#{date3}'",:joins => "as b inner join carts as c on c.book_id = b.id")
我并不是说ActiveRecord无法处理这个查询,但是为了便于阅读(或者还有其他我还不知道的限制),它是否更容易被原始sql所接受?
解决方法
一般的想法是尽可能地坚持ActiveRecord生成的查询,并仅在必要时使用sql片段.显式支持sql片段,因为ActiveRecord的创建者意识到sql无法完全抽象掉.
使用不带sql片段的find方法通常会获得更好的可维护性.举个例子,尝试:
Book.find(:all,:conditions => ["created_at >= ? AND created_at <= ? AND updated_at <= ?",date1,date2,date3] :include => :carts)
:inlude => :如果您将has_many:cart添加到Book模型,则购物车将进行加入.如您所见,不必涉及太多sql.即使输入的引用和转义也可以留给Rails,同时仍然使用sql文字来处理> =和< =运算符. 更进一步,你可以让它更清晰:
class Book < AciveRecord::Base # Somewhere in your Book model: named_scope :created_between,lambda { |start_date,end_date| { :conditions => { :created_at => start_date..end_date } } } named_scope :updated_before,lambda { |date| { :conditions => ["updated_at <= ?",date] } } # ... end Book.created_between(date1,date2).updated_before(date3).find(:all,:include => :carts)
更新:named_scopes的重点当然是重用条件.由您来决定是否将一组条件放入命名范围是否有意义.