2012-06-25 32 views
3

我正在使用Ruby on Rails 3.2.2,並且正在試驗Squeel gem。我想知道如果(以某種方式,使用Squeel gem或不),可以在where子句中「直接」添加與scope方法相關的SQL子句。也就是說,我有:是否可以在`where'方法/子句中「添加」與`scope`方法有關的SQL子句?

class Article < ActiveRecord::Base 
    # Note: This is a scope method. 
    def self.created_by(user) 
    where(:user_id => user.id) 
    end 

    # I would like to use a scope method like the following. 
    # 
    # Note: Code in the following method doesn't work, but it should help 
    # understanding what I mean. 
    def self.scope_method_name(user) 
    where{ created_by(user) | ... & ... } 
    end 
end 

所以,當我運行Article.scope_method_name(@current_user).to_sql那麼它應該返回類似以下內容:

SELECT articles.* FROM articles WHERE articles.user_id = 1 OR ... AND ... 

我tryed sifters但那些(至少對我來說),意在在其他Squeel聲明中僅使用。也就是說,如果我聲明一個篩選器,那麼我不能使用它來範圍ActiveRecord s,因爲該篩選器返回Squeel::Nodes::Predicate對象而不是ActiveRecord::Relation

回答

1

你必須分解成多個原始AREL跌幅爲OR操作

def self.scope_method_name(user) 
    t = arel_table 
    where(
    (t[:user_id].eq(user.id).or(
    t[:blah].eq('otherthing') 
    ).and([:bleh].eq('thirdthing')) 
    ) 
end 

或者類似的規定。

0

您可以鏈接範圍如Article.by_author(user).by_editor(),但是這會將所有條件與ANDs連接起來。因此,要解決這個問題,你可以寫個人的作用域(不鏈接它們)使用Squeel,如:

class Article < ActiveRecord::Base 

    scope :by_author, ->(user) { where{author_id == user.id} } 
    scope :by_editor, ->(user) { where{editor_id == user.id} } 
    scope :by_title, ->(token) { where{title =~ "%#{token}%"} } 
    scope :by_author_or_editor, ->(user) { where{(author_id == user.id)|(editor_id == user.id)} } 
    scope :by_author_or_editor_and_title, ->(user, token) { where{((author_id == user.id)|(editor_id == user.id))&(title =~ "%#{token}%")} } 
end 

或者你可以用篩子:

class Article < ActiveRecord::Base 

    sifter :sift_author do |user| 
    author_id == user.id 
    end 

    sifter :sift_editor do |user| 
    editor_id == user.id 
    end 

    sift :sift_title do |token| 
    title =~ "%#{token}%" 
    end 

    scope :by_author, ->(user) { where{sift :sift_author, user} } 
    scope :by_editor, ->(user) { where{sift :sift_editor, user} } 
    scope :by_title, ->(token) { where{sift :sift_title, token} } 
    scope :by_author_or_editor, -> (user) { where{(sift :sift_author, user)|(sift :sift_editor, user)} } 
    scope :by_author_or_editor_and_title, ->(user, token) { where{((sift :sift_author, user)|(sift :sift_editor, user))&(sift :sift_title, token)} } 
end 

此向你作用域返回一個ActiveRecord ::關係,所以你可以在理論上進一步鏈接它們。