Zab*_*bba 15 activerecord ruby-on-rails-3
我正在尝试从AREL获取SQL,但是在我使用的情况下它不起作用average(:stars):
这有效:
Review.where("reviewed_user_id = ?", self.reviewed_user_id).to_sql
#=> "SELECT `reviews`.* FROM `reviews` WHERE (reviewed_user_id = 3)"
Run Code Online (Sandbox Code Playgroud)
这导致NoMethodError:
Review.where("reviewed_user_id = ?", self.reviewed_user_id).average(:stars).to_sql
#=> undefined method `to_sql' for 3:Fixnum
Run Code Online (Sandbox Code Playgroud)
这意味着to_sql调用AREL的结果而不是AREL对象 - 但为什么呢?
如何获取生成的SQL?
Jon*_*ran 26
发生这种情况的原因是因为平均方法是开启的ActiveRecord::Relation,而不是Arel,它会强制计算.
m = Review.where('id = ?', 42).method(:average)
#=> #<Method: ActiveRecord::Relation(ActiveRecord::Calculations)#average>
m.source_location # or m.__file__ if you're on a different version of Ruby
#=> ["/Users/jtran/.rvm/gems/ruby-1.9.2-p0/gems/activerecord-3.0.4/lib/active_record/relation/calculations.rb", 65]
Run Code Online (Sandbox Code Playgroud)
通过检查内部ActiveRecord::Calculations,您可以获得如何获取它使用的SQL.
my_reviewed_user_id = 42
relation = Review.where('reviewed_user_id = ?', my_reviewed_user_id)
column = Arel::Attribute.new(Review.unscoped.table, :stars)
relation.select_values = [column.average]
relation.to_sql
#=> "SELECT AVG(\"reviews\".\"stars\") AS avg_id FROM \"reviews\" WHERE (reviewed_user_id = 42)"
Run Code Online (Sandbox Code Playgroud)
如果你在控制台工作,请小心. ActiveRecord::Relation缓存的事情如果你逐行在控制台中输入上述内容,它实际上是行不通的,因为漂亮的打印会强制关系.但是,用分号分隔上面的内容并没有换行.
或者,您可以直接使用Arel,如下所示:
my_reviewed_user_id = 42
reviews = Arel::Table.new(:reviews)
reviews.where(reviews[:reviewed_user_id].eq(my_reviewed_user_id)).project(reviews[:stars].average).to_sql
#=> "SELECT AVG(\"reviews\".\"stars\") AS avg_id FROM \"reviews\" WHERE \"users\".\"reviewed_user_id\" = 42"
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7388 次 |
| 最近记录: |