我需要为当前用户(另一名员工)的“收藏夹”显示一个UI元素(例如星号或复选标记)。
Employee模型定义了以下关系以支持此:
has_and_belongs_to_many :favorites, :class_name => "Employee", :join_table => "favorites",
:association_foreign_key => "favorite_id", :foreign_key => "employee_id"
收藏夹有两个字段:employee_id,favorite_id。
如果我要编写SQL,以下查询将为我提供我想要的结果:
SELECT id, account,
IF(
(
SELECT favorite_id
FROM favorites
WHERE favorite_id=p.id
AND employee_id = ?
) IS NULL, FALSE, TRUE) isFavorite
FROM employees
哪里'?'将由会话[:user_id]替换。
如何在Rails中表示isFavorite标量查询?
另一种方法是使用这样的查询:
SELECT id, account, IF(favorite_id IS NULL, FALSE, TRUE) isFavorite
FROM employees e
LEFT OUTER JOIN favorites f ON e.id=f.favorite_id
AND employee_id = ?
再次,'?'由会话[:user_id]值替换。
我在Rails中写了一些成功:
ee=Employee.find(:all, :joins=>"LEFT OUTER JOIN favorites ON employees.id=favorites.favorite_id AND favorites.employee_id=1", :select=>"employees.*,favorites.favorite_id")
不幸的是,当我尝试用“?”替换“1”来使这个查询“动态”时,我会收到错误。
ee=Employee.find(:all, :joins=>["LEFT OUTER JOIN favorites ON employees.id=favorites.favorite_id AND favorites.employee_id=?",1], :select=>"employees.*,favorites.favorite_id")
显然,我的语法错误,但可以:将表达式加入'动态'吗?这是Lambda表达式的情况吗?
我希望为此查询添加其他过滤器,并将其与will_paginate和acts_as_taggable_on一起使用,如果这会产生影响。
修改
尝试使:joins
动态出错:
ActiveRecord::ConfigurationError: Association named 'LEFT OUTER JOIN favorites ON employees.id=favorites.favorite_id AND favorites.employee_id=?' was not found; perhaps you misspelled it?
from /Users/craibuc/.gem/ruby/1.8/gems/activerecord-2.3.5/lib/active_record/associations.rb:1906:in `build'
from /Users/craibuc/.gem/ruby/1.8/gems/activerecord-2.3.5/lib/active_record/associations.rb:1911:in `build'
from /Users/craibuc/.gem/ruby/1.8/gems/activerecord-2.3.5/lib/active_record/associations.rb:1910:in `each'
from /Users/craibuc/.gem/ruby/1.8/gems/activerecord-2.3.5/lib/active_record/associations.rb:1910:in `build'
from /Users/craibuc/.gem/ruby/1.8/gems/activerecord-2.3.5/lib/active_record/associations.rb:1830:in `initialize'
from /Users/craibuc/.gem/ruby/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:1789:in `new'
from /Users/craibuc/.gem/ruby/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:1789:in `add_joins!'
from /Users/craibuc/.gem/ruby/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:1686:in `construct_finder_sql'
from /Users/craibuc/.gem/ruby/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:1548:in `find_every'
from /Users/craibuc/.gem/ruby/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:615:in `find'
答案 0 :(得分:3)
试试这个:
ee=Employee.all(
:select=>"employees.*,favorites.favorite_id",
:joins=>"LEFT OUTER JOIN favorites AS favorites
ON employees.id=favorites.favorite_id AND
favorites.employee_id = #{session[:user_id]}")
或者确切地说:
joins = Employee.send(:sanitize_sql_array,
["LEFT OUTER JOIN favorites AS favorites
ON employees.id=favorites.favorite_id AND
favorites.employee_id = ? ", session[:user_id]
])
ee=Employee.find(:all,
:select=>"employees.*,favorites.favorite_id",
:joins=> joins )
第二种方法解决了SQL注入问题。
修改1
要在irb
中测试这些来电,请执行以下操作:
通过创建哈希来模拟会话对象:
>> session = {:user_id => "1" }
session = {:user_id => "1" }
=> {:user_id=>"1"}
执行取景器:
>> ee=Employee.find(:all,
:select=>"employees.*,favorites.favorite_id",
:joins=>"LEFT OUTER JOIN favorites AS favorites
ON employees.id=favorites.favorite_id AND
favorites.employee_id = #{session[:user_id]}")
答案 1 :(得分:0)
我想两种方式都是可能的,但通常情况下,我会在WHERE
子句(:conditions
)中坚持使用条件:
ee = Employee.find(:all,
:select => 'employees.*, favorites.favorite_id',
:conditions => ['favorites.employee_id = ?', 1],
:joins => 'LEFT OUTER JOIN favorites ON employees.id = favorites.favorite_id'
)
答案 2 :(得分:0)
:joins
需要原始字符串或符号(关联名称)或关联数组。所以你不能拥有动态条件。
请参阅参数部分here。