2016-01-23 36 views
1

我在下面找到類似的東西。使用條件構造where子句。紅寶石有可能嗎?或者我需要將它分成兩個where子句?如何在ruby中使用if構造where子句

Post 
    .where(tag: "A") if condition A 
    .where(tag: "B") if condition B 
    .where(user_id: 1) 
    .order(....) 

其實我的情況就是這樣。有什麼辦法可以處理?

def this_function      
    @questions = Question.joins(:comment_threads) 
          .tagged_with(tag_variable, wild: true, any: true) if tag_variable.present? 
          .where(index_where_clause) 
          .where("questions.created_at < ?", query_from_date_time) 
          .order(created_at: :desc).limit(5) 
end 
    def index_where_clause 
    where_clause = {} 
    where_clause[:user_detail_id] = current_user_detail.id if params[:type] == "my_question" 
    where_clause[:comments] = {user_detail_id: current_user_detail.id} if params[:type] == "my_answer" 
    where_clause[:wine_question_score_id] = params[:wine_question_score_id] if params[:wine_question_score_id].present? 
    where_clause 
    end 
+0

我剛纔編輯這個問題。 – travistam

+0

沒有必要告訴我們你編輯過任何東西。我們可以告訴。相反,只需在最初/最初應該放置的實體中添加更改即可。 –

回答

2

你使用回報關係的方法,所以你可以說這樣的事情:

@questions = Question.joins(:comment_threads) 
@questions = @questions.where("questions.created_at < ?", query_from_date_time) 
@questions = @questions.tagged_with(tag_variable, wild: true, any: true) if tag_variable.present? 
@questions = @questions.where(:user_detail_id => current_user_detail.id) if params[:type] == "my_question" 
@questions = @questions.where(:comments => { user_detail_id: current_user_detail.id}) if params[:type] == "my_answer" 
@questions = @questions.where(:wine_question_score_id => params[:wine_question_score_id]) if params[:wine_question_score_id].present? 
@questions = @questions.order(created_at: :desc).limit(5) 

並根據您在params中的內容逐個構建查詢。

我可能會打破它多一點:

def whatever 
    @questions = Question.joins(:comment_threads) 
    @questions = @questions.where("questions.created_at < ?", query_from_date_time) 
    @questions = with_tag(@questions, tag_variable) 
    #... 
    @questions = @questions.order(created_at: :desc).limit(5) 
    end 

private 

    def with_tag(q, tag) 
    if tag.present? 
     q.tagged_with(tag, wild: true, any: true) 
    else 
     q 
    end 
    end 

    #... 

埋葬所有的嘈雜位的小方法,讓事情更清潔和更容易閱讀。如果您不止一次這樣做,那麼您可以使用示波器來隱藏模型類中的噪聲,並根據需要重新使用它。

+1

這是我要添加的答案,如果它不在這裏。主動關係就像任何其他......不是不可分開的神奇列車殘骸。 –

+1

@WayneConrad:是的,人們似乎忘記了Ruby有對象和類,而不僅僅是哈希和Rails給你的任何時期。 –

+0

謝謝。這應該是最好的答案 – travistam

0

你可以做到以下幾點:

condition = {:tag => "A"} if condition A 
condition = {:tag => "B"} if condition B 

Post 
    .where(condition) 
    .where(:user_id => 1) 
    .order(....) 
+0

所以最好的方法是將查詢分爲兩部分? – travistam

+0

我會先確定條件,然後用它來創建查詢。這樣你甚至可以用單獨的方法分離出條件的計算。 – Atri

0

,你必須使用scope

scope :my_scope, -> (variable) { where(some: vatiable) if my_condition } 
1

#tap可以爲地方修改對象申請條件邏輯是有幫助的,在這種情況下,對象將是你.where條件:

Post 
.where(
    { user_id: 1 } 
    .tap do |conditions| 
    conditions[:tag] = 'A' if condition A 
    conditions[:tag] = 'B' if condition B 
    end 
) 
.order(...) 

或者,也許這是一個少許清潔劑,如果你創建的helper方法:

def specific_conditions 
    { user_id: 1 }.tap do |conditions| 
    conditions[:tag] = 'A' if condition A 
    conditions[:tag] = 'B' if condition B 
    end 
end 

Post.where(specific_conditions).order(...) 

但作爲一個側面說明,如果有其中condition Acondition B既可以是真實的情況下,第二conditions[:tag] = ...線將覆蓋第一。如果沒有兩種情況都是正確的,你可以嘗試使用某種集合來查找標籤的正確值。

CONDITION_TAGS = { 
    a: 'A'.freeze, 
    b: 'B'.freeze, 
}.freeze 

def specific_conditions 
    { user_id: 1 } 
    .tap do |conditions| 
    conditions[:tag] = CONDITION_TAGS[condition_value] if condition_value 
    end 
end 

Post.where(specific_conditions).order(...) 
1
#in Question class 
scope :with_user_detail, -> (user_detail_id, flag=true) do 
    where("user_detail_id = ?", user_detail_id) if flag 
end 

scope :with_user_detail_comments, -> (user_detail_id, flag=true) do 
    joins(:comment_threads).where("comments.user_detail_id = ?", user_detail_id) if flag 
end 

scope :with_wine_question_score, -> (wine_question_score_id) do 
    where("wine_question_score_id = ?", wine_question_score_id) if wine_question_score_id.present? 
end 

scope :tagged_with_condition, -> (tag_variable, wild, any) do 
    tagged_with(tag_variable, wild, any) if tag_variable.present? 
end 

def this_function 
    my_question_flag = params[:type] == "my_question" 
    my_answer_flag = params[:type] == "my_answer" 
    Question.with_user_detail(current_user_detail.id, my_question_flag) 
    .tagged_with_condition(tag_variable, wild: true, any: true) 
    .with_user_detail_comments(current_user_detail.id, my_answer_flag) 
    .with_wine_question_score(params[:wine_question_score_id]) 
    .order(created_at: :desc).limit(5) 
end