2017-02-08 4 views
0

Dieser Bereich sollte optionale Schlüssel im übergebenen Hash behandeln. Wenn die Schlüssel "Organisation" und "Website" vorhanden sind, sollten beide zusammen angekettet werden.Bedingte Verkettung in einem Bereich

scope :search_provider, lambda { |search| 
    if search['organisation'].present? 
    where("name COLLATE utf8_general_ci LIKE ?", "%#{search['organisation']}%") 
    end 
    if search['website'].present? 
    where("website COLLATE utf8_general_ci LIKE ?", "%#{search['website']}%") 
    end 
} 

Aber leider das ist nicht der Fall:

Provider.search_provider({'website' => 'Hello'}).to_sql 
=> "SELECT `provider`.* FROM `providers` WHERE (website COLLATE utf8_general_ci LIKE '%Hello%')" 

[OK]

Provider.search_provider({'organisation' => 'Hello'}).to_sql 
=> "SELECT `provider`.* FROM `providers`" 

[FALSCH]

Provider.search_provider({'website' => 'Hello', 'organisation' => 'huhu'}).to_sql 
=> "SELECT `provider`.* FROM `providers` WHERE (website COLLATE utf8_general_ci LIKE '%Hello%')" 

[FALSCH]

Nur die letzte where (Website) verwendet wird und die erste where (Organisation) verloren. Ich denke, das Problem ist der fehlende Fall sonst ... Ich habe es mit where(nil) versucht, aber es hat nicht funktioniert.

Wie behebe ich es?

Edit:

Ich kann mit einem bedingten arbeiten wie

if search['organisation'].present? && search['website'].present? 
    ... 
elsif search['organisation'].present? 
    ... 
elsif search['website'].present? 
    ... 

aber ich möchte mehr Schlüssel in der Hash einfügen und die bedingte Anweisung wäre ziemlich groß werden mit 6 oder 7 Tasten zu in Betracht ziehen ..

Antwort

1

Sie können Umfang wie diese hier verwenden:

scope :search_provider, ->(search) { 
scope = where('TRUE') 
if search['organisation'].present? 
    scope = scope.where({ :some_condition => :some_value }) 
end 
if search['website'].present? 
    scope = scope.where({ :some_condition => :some_value }) 
end 
scope 
} 
1

scope ist wirklich nur ein syntaktischer Zucker für deklarierende Klassenmethoden. Verwenden Sie nicht scope, wenn es nicht in eine saubere kleine Einlage passt.

Wenn Sie es als formale Klassenmethode deklarieren, ist es viel einfacher zu strukturieren.

def self.search(**kwargs) 
    kwargs.compact.each_with_object(self.all) do |(key, value), memo| 
    memo.where("? COLLATE utf8_general_ci LIKE ?", key.to_s, value) 
    end 
end 

Sie würden es von Ihrem Controller rufen #permit oder #slice auf einen Hash verwenden.

@providers = Provider.search(params.permit(:organisation, :website)) 
Verwandte Themen