2013-03-18 57 views
0

我有一個數據庫Item s。每件商品belongs_to a User。每個項目有一個visibilitystatus字段。爲了搜索,一個項目必須滿足下列規則:如何使用activerecord在rails中正確寫入複雜的where子句?

status must be :available 
    AND 
    (visibility must be :everyone 
    OR 
    (visibility must be :friends AND user_id must be in current_user.friends) 
) 

換句話說,你可以看到所有可用的公共物品,你可以看到你朋友的「私人」物品。

如何檢索出符合此條件的物品?


我曾嘗試以下:

class Item < ActiveRecord::Base 

    belongs_to :user 
    attr_accessible :description, :photo, :title, :user_id, :visibility 

    #... 

    scope :searchable, lambda { |user| 
    where('status IN ? AND (visibility IN ? OR (visibility IN ? AND user_id IN ?))', 
      [:available, :lent], 
      [:everyone], 
      [:friends], 
      user.friends) 
    } 
end 

而且在我的控制器:

@items = Item.searchable(current_user) 

但我有一個錯誤:

周圍沒有括號所產生條款

ActiveRecord::StatementInvalid in Items#search 

SQLite3::SQLException: near ",": syntax error: SELECT "items".* FROM "items" WHERE (status IN 'available','lent' AND (visibility IN 'everyone' OR (visibility IN 'friends' AND user_id IN 'foo'))) 
+0

如果您手動添加圓括號,該怎麼辦? ''where('status IN(?)...' – MurifoX 2013-03-18 11:45:13

+0

另外,爲什麼我不能用'do'來代替lambda的{{'| – 2013-03-18 11:50:21

+0

我相信這是一種慣例,我從來沒有見過ActiveRecord作用域與do ... end lambda塊 – MurifoX 2013-03-18 11:55:44

回答

2

好了,我不知道你有把括號自己周圍的? S(如你所說@MurifoX)

scope :searchable, lambda { |user| 
    where('status IN (?) AND (visibility IN (?) OR (visibility IN (?) AND user_id IN (?)))', 
      [:available, :lent], 
      [:everyone], 
      [:friends], 
      user.friends) 
} 

我仍然敞開,如果有實現更好的辦法這種行爲。

+0

你的where子句是一個字符串,在你有'SQL'語句'IN'的字符串中,ActiveRecord不能解析這個字符串,所以括號會自動出現。可以做的只是在準備的語句中替換'?'。 – MurifoX 2013-03-18 11:52:40

4

我個人比較喜歡用lambda聲明一個超類範圍的類方法。我認爲閱讀起來比較容易。另外,設置默認值更容易。

def self.with_status(statuses) 
    where(status: statuses) 
end 

def self.visible_to_friends_of(user) 
    where('visibility = ? OR (visibility = ? AND user_id IN (?))', 
    'everyone', 
    'friends', 
    user.friends 
) 
end 

def self.searchable(user) 
    with_status([:available, :lent]).visible_to_friends_of(user) 
end 
0

我想你應該用think_sphinx gem來做這個。

define_index do 
indexes title 
indexes description 
indexes uploads.file_file_name, :as => :upload_file_name 
indexes uploads.file_content_type, :as => :upload_file_content_type 

has :id 
has price 
has user_id 
has created_at 
has purchase_count 
has images.photo_file_size 
has tags.id, :as => :tag_id, :facet => true 
has tags.parent_id, :as => :tag_parent_id, :facet => true 
has "state='active'", :as => :active, :type => :boolean, :facet => true 
has "count(images.id) > 0", :as => :has_image, :type => :boolean 
has "sum(uploads.file_file_size)", :as => :total_size, :type => :integer 

where "state in ('active', 'pending')" 

set_property :delta => true 
set_property :morphology => 'stem_en' 
set_property :min_prefix_len => 3 
set_property :enable_star => true 

,以滿足您的要求,您可以使用具有條件或where子句。 您在點擊瞭解詳情here

相關問題